Merge pull request #335 from ente-io/sharable-url-patches

Sharable url patches
This commit is contained in:
Abhinav Kumar 2022-01-29 12:52:34 +05:30 committed by GitHub
commit 22ae94821c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 138 additions and 71 deletions

View file

@ -52,6 +52,8 @@ function CollectionShare(props: Props) {
props.collection.key
);
setPublicShareUrl(t);
} else {
setPublicShareUrl(null);
}
};
main();

View file

@ -97,8 +97,8 @@ const BannerContainer = styled.div<{ span: number }>`
`;
const ReportAbuseItem = styled.div<{ span: number }>`
flex: 1;
text-align: right;
display: flex;
justify-content: center;
grid-column: span ${(props) => props.span};
& > p {
margin: 0;
@ -288,7 +288,7 @@ export function PhotoList({
item: (
<ReportAbuseItem span={columns}>
<LinkButton
style={{ fontSize: '16px' }}
style={{ fontSize: '14px' }}
variant={ButtonVariant.danger}
onClick={publicCollectionGalleryContext.openReportForm}>
{constants.ABUSE_REPORT_BUTTON_TEXT}

View file

@ -226,7 +226,9 @@ export function AbuseReportForm({ show, close, url }: Iprops) {
<Form.Group controlId="reportForm.email">
<Form.Control
type="text"
placeholder={constants.ENTER_EMAIL}
placeholder={
constants.ENTER_EMAIL_ADDRESS
}
value={values.email}
onChange={handleChange('email')}
isInvalid={Boolean(

View file

@ -7,9 +7,7 @@ interface Iprops {
}
const Info = styled.h5`
padding: 5px 24px;
margin: 20px;
border-bottom: 2px solid #5a5858;
`;
export function CollectionInfo(props: Iprops) {

View file

@ -10,6 +10,7 @@ const Wrapper = styled.div`
`;
const NoStyleAnchor = styled.a`
color: inherit;
text-decoration: none !important;
&:hover {
color: #fff !important;
@ -20,7 +21,7 @@ export const ButtonWithLink = ({
href,
children,
}: React.PropsWithChildren<{ href: string }>) => (
<Button variant="outline-success">
<Button id="go-to-ente">
<NoStyleAnchor href={href}>{children}</NoStyleAnchor>
</Button>
);

View file

@ -232,6 +232,17 @@ const GlobalStyles = createGlobalStyle`
.btn-outline-danger, .btn-outline-secondary, .btn-outline-primary{
border-width: 2px;
}
#go-to-ente{
background:none;
border-color: #3dbb69;
color:#51cd7c;
}
#go-to-ente:hover, #go-to-ente:focus, #go-to-ente:active {
color:#fff;
background-color: #44774d;
}
a {
color: #fff;
}

View file

@ -178,7 +178,7 @@ export default function Gallery() {
const loadingBar = useRef(null);
const [isInSearchMode, setIsInSearchMode] = useState(false);
const [searchStats, setSearchStats] = useState(null);
const isLoadingBarRunning = useRef(true);
const isLoadingBarRunning = useRef(false);
const syncInProgress = useRef(true);
const resync = useRef(false);
const [deleted, setDeleted] = useState<number[]>([]);

View file

@ -137,7 +137,7 @@ export default function LandingPage() {
hash: currentURL.hash,
}
);
setLoading(false);
await initLocalForage();
};
const handleNormalRedirect = async () => {
@ -145,6 +145,10 @@ export default function LandingPage() {
if (user?.email) {
await router.push(PAGES.VERIFY);
}
await initLocalForage();
};
const initLocalForage = async () => {
try {
await localForage.ready();
} catch (e) {

View file

@ -32,7 +32,7 @@ export default function PublicCollectionGallery() {
const token = useRef<string>(null);
const collectionKey = useRef<string>(null);
const url = useRef<string>(null);
const [publicFiles, setPublicFiles] = useState<EnteFile[]>(null);
const [publicFiles, setPublicFiles] = useState<EnteFile[]>([]);
const [publicCollection, setPublicCollection] = useState<Collection>(null);
const appContext = useContext(AppContext);
const [abuseReportFormView, setAbuseReportFormView] = useState(false);
@ -42,14 +42,23 @@ export default function PublicCollectionGallery() {
const openReportForm = () => setAbuseReportFormView(true);
const closeReportForm = () => setAbuseReportFormView(false);
const loadingBar = useRef(null);
const [isLoadingBarRunning, setIsLoadingBarRunning] = useState(false);
const openMessageDialog = () => setMessageDialogView(true);
const closeMessageDialog = () => setMessageDialogView(false);
const startLoading = () => loadingBar.current?.continuousStart();
const finishLoading = () => loadingBar.current?.complete();
const startLoading = () => {
!isLoadingBarRunning && loadingBar.current?.continuousStart();
setIsLoadingBarRunning(true);
};
const finishLoading = () => {
loadingBar.current?.complete();
setIsLoadingBarRunning(false);
};
useEffect(() => {
appContext.showNavBar(true);
setLoading(false);
const currentURL = new URL(window.location.href);
if (currentURL.pathname !== PAGES.ROOT) {
router.push(
@ -68,32 +77,28 @@ export default function PublicCollectionGallery() {
const main = async () => {
const worker = await new CryptoWorker();
url.current = window.location.href;
const urlS = new URL(url.current);
const eToken = urlS.searchParams.get('t');
const eCollectionKey = urlS.hash.slice(1);
const decodedCollectionKey = await worker.fromHex(eCollectionKey);
if (!eToken || !decodedCollectionKey) {
const currentURL = new URL(url.current);
const t = currentURL.searchParams.get('t');
const ck = currentURL.hash.slice(1);
const dck = await worker.fromHex(ck);
if (!t || !dck) {
setLoading(false);
return;
}
token.current = eToken;
collectionKey.current = decodedCollectionKey;
token.current = t;
collectionKey.current = dck;
url.current = window.location.href;
const localCollection = await getLocalPublicCollection(
eCollectionKey
collectionKey.current
);
if (localCollection) {
setPublicCollection(localCollection);
const localPublicFiles = sortFiles(
mergeMetadata(
await getLocalPublicFiles(`${localCollection.id}`)
)
mergeMetadata(await getLocalPublicFiles(localCollection))
);
setPublicFiles(localPublicFiles);
setLoading(false);
}
syncWithRemote();
appContext.showNavBar(true);
};
main();
}, []);
@ -119,7 +124,6 @@ export default function PublicCollectionGallery() {
setPublicFiles(null);
}
} finally {
setLoading(false);
finishLoading();
}
};
@ -132,7 +136,7 @@ export default function PublicCollectionGallery() {
</Container>
);
}
if (!publicFiles) {
if (!isLoadingBarRunning && !publicFiles) {
return <Container>{constants.NOT_FOUND}</Container>;
}
return (
@ -154,7 +158,7 @@ export default function PublicCollectionGallery() {
favItemIds={null}
setSelected={() => null}
selected={{ count: 0, collectionID: null }}
isFirstLoad={false}
isFirstLoad={true}
openFileUploader={() => null}
isInSearchMode={false}
search={{}}

View file

@ -25,8 +25,16 @@ class PublicCollectionDownloadManager {
}
if (!this.thumbnailObjectURLPromise.get(file.id)) {
const downloadPromise = async () => {
const thumbnailCache = await caches.open('thumbs');
const cacheResp: Response = await thumbnailCache.match(
const thumbnailCache = await (async () => {
try {
return await caches.open('thumbs');
} catch (e) {
return null;
// ignore
}
})();
const cacheResp: Response = await thumbnailCache?.match(
file.id.toString()
);
if (cacheResp) {
@ -35,7 +43,7 @@ class PublicCollectionDownloadManager {
const thumb = await this.downloadThumb(token, file);
const thumbBlob = new Blob([thumb]);
try {
await thumbnailCache.put(
await thumbnailCache?.put(
file.id.toString(),
new Response(thumbBlob)
);

View file

@ -18,17 +18,25 @@ const ENDPOINT = getEndpoint();
const PUBLIC_COLLECTION_FILES_TABLE = 'public-collection-files';
const PUBLIC_COLLECTIONS_TABLE = 'public-collections';
const getCollectionUID = (collection: Collection) => `${collection.id}`;
const getCollectionUID = (collection: Collection) => `${collection.key}`;
const getCollectionSyncTimeUID = (collectionUID: string) =>
`public-${collectionUID}-time`;
export const getLocalPublicFiles = async (collectionUID: string) => {
const localSavedPublicCollectionFiles = (
(await localForage.getItem<LocalSavedPublicCollectionFiles[]>(
PUBLIC_COLLECTION_FILES_TABLE
)) ?? []
).find(
(localSavedPublicCollectionFiles) =>
localSavedPublicCollectionFiles.collectionUID === collectionUID
) || { collectionKey: null, files: [] as EnteFile[] };
export const getLocalPublicFiles = async (collection: Collection) => {
const localSavedPublicCollectionFiles =
(
(await localForage.getItem<LocalSavedPublicCollectionFiles[]>(
PUBLIC_COLLECTION_FILES_TABLE
)) || []
).find(
(localSavedPublicCollectionFiles) =>
localSavedPublicCollectionFiles.collectionUID ===
getCollectionUID(collection)
) ||
({
collectionUID: null,
files: [] as EnteFile[],
} as LocalSavedPublicCollectionFiles);
return localSavedPublicCollectionFiles.files;
};
export const savePublicCollectionFiles = async (
@ -38,20 +46,22 @@ export const savePublicCollectionFiles = async (
const publicCollectionFiles =
(await localForage.getItem<LocalSavedPublicCollectionFiles[]>(
PUBLIC_COLLECTION_FILES_TABLE
)) ?? [];
await localForage.setItem(PUBLIC_COLLECTION_FILES_TABLE, [
...publicCollectionFiles,
{ collectionUID, files },
]);
)) || [];
await localForage.setItem(
PUBLIC_COLLECTION_FILES_TABLE,
dedupeCollectionFiles([
{ collectionUID, files },
...publicCollectionFiles,
])
);
};
export const getLocalPublicCollection = async (collectionKey: string) => {
const localCollections =
(await localForage.getItem<Collection[]>(PUBLIC_COLLECTIONS_TABLE)) ||
[];
const publicCollection =
(
(await localForage.getItem<Collection[]>(
PUBLIC_COLLECTIONS_TABLE
)) ?? []
).find(
localCollections.find(
(localSavedPublicCollection) =>
localSavedPublicCollection.key === collectionKey
) || null;
@ -62,19 +72,47 @@ export const savePublicCollection = async (collection: Collection) => {
const publicCollections =
(await localForage.getItem<Collection[]>(PUBLIC_COLLECTIONS_TABLE)) ??
[];
await localForage.setItem(PUBLIC_COLLECTIONS_TABLE, [
...publicCollections,
collection,
]);
await localForage.setItem(
PUBLIC_COLLECTIONS_TABLE,
dedupeCollections([collection, ...publicCollections])
);
};
const dedupeCollections = (collections: Collection[]) => {
const keySet = new Set([]);
return collections.filter((collection) => {
if (!keySet.has(collection.key)) {
keySet.add(collection.key);
return true;
} else {
return false;
}
});
};
const dedupeCollectionFiles = (
collectionFiles: LocalSavedPublicCollectionFiles[]
) => {
const keySet = new Set([]);
return collectionFiles.filter(({ collectionUID }) => {
if (!keySet.has(collectionUID)) {
keySet.add(collectionUID);
return true;
} else {
return false;
}
});
};
const getPublicCollectionLastSyncTime = async (collectionUID: string) =>
(await localForage.getItem<number>(`public-${collectionUID}-time`)) ?? 0;
(await localForage.getItem<number>(
getCollectionSyncTimeUID(collectionUID)
)) ?? 0;
const setPublicCollectionLastSyncTime = async (
collectionUID: string,
time: number
) => await localForage.setItem(collectionUID, time);
) => await localForage.setItem(getCollectionSyncTimeUID(collectionUID), time);
export const syncPublicFiles = async (
token: string,
@ -83,9 +121,7 @@ export const syncPublicFiles = async (
) => {
try {
let files: EnteFile[] = [];
const localFiles = await getLocalPublicFiles(
getCollectionUID(collection)
);
const localFiles = await getLocalPublicFiles(collection);
files.push(...localFiles);
try {
if (!token) {

View file

@ -627,19 +627,20 @@ const englishConstants = {
MALICIOUS_CONTENT: 'contains malicious content',
COPYRIGHT:
'infringes on the copyright of someone I am authorized to represent',
SELECT_REASON: 'select a reason',
ENTER_FULL_NAME: 'full name',
ENTER_EMAIL_ADDRESS: 'email*',
SELECT_REASON: 'select a reason*',
ENTER_FULL_NAME: 'full name*',
ENTER_DIGITAL_SIGNATURE:
'typing your full name in this box will act as your digital signature',
ENTER_ON_BEHALF_OF: 'I am reporting on behalf of',
ENTER_ADDRESS: 'address',
ENTER_JOB_TITLE: 'job title',
ENTER_CITY: 'city',
ENTER_PHONE: 'phone number',
'typing your full name in this box will act as your digital signature*',
ENTER_ON_BEHALF_OF: 'I am reporting on behalf of*',
ENTER_ADDRESS: 'address*',
ENTER_JOB_TITLE: 'job title*',
ENTER_CITY: 'city*',
ENTER_PHONE: 'phone number*',
ENTER_STATE: 'state',
ENTER_POSTAL_CODE: 'zip/postal code',
ENTER_COUNTRY: 'country',
ENTER_STATE: 'state*',
ENTER_POSTAL_CODE: 'zip/postal code*',
ENTER_COUNTRY: 'country*',
JUDICIAL_DESCRIPTION: () => (
<>
By checking the following boxes, I state{' '}