1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-11-29 22:48:10 +02:00

Mobile: Joplin Cloud/Server: Support publishing notes (#12350)

This commit is contained in:
Henry Heino
2025-06-06 15:04:09 -07:00
committed by GitHub
parent 0fc665d6d8
commit 3d2ac91b8a
11 changed files with 492 additions and 76 deletions

View File

@@ -0,0 +1,12 @@
import ShareService from '../../../services/share/ShareService';
interface UnshareNoteEvent {
noteId: string;
}
const onUnshareNoteClick = async (event: UnshareNoteEvent) => {
await ShareService.instance().unshareNote(event.noteId);
await ShareService.instance().refreshShares();
};
export default onUnshareNoteClick;

View File

@@ -0,0 +1,9 @@
// eslint-disable-next-line import/prefer-default-export -- types file with a single type
export enum SharingStatus {
Unknown = 'unknown',
Synchronizing = 'synchronizing',
Creating = 'creating',
Idle = 'idle',
Created = 'created',
}

View File

@@ -0,0 +1,9 @@
import { _ } from '../../../locale';
import { getEncryptionEnabled } from '../../../services/synchronizer/syncInfoUtils';
const useEncryptionWarningMessage = () => {
if (!getEncryptionEnabled()) return null;
return _('Note: When a note is shared, it will no longer be encrypted on the server.');
};
export default useEncryptionWarningMessage;

View File

@@ -0,0 +1,88 @@
import Logger from '@joplin/utils/Logger';
import JoplinServerApi from '../../../JoplinServerApi';
import { reg } from '../../../registry';
import { NoteEntity } from '../../../services/database/types';
import ShareService from '../../../services/share/ShareService';
import { StateShare } from '../../../services/share/reducer';
import shim from '../../../shim';
import { SharingStatus } from './types';
const { useCallback } = shim.react();
const logger = Logger.create('useOnShareLinkClick');
interface Props {
notes: NoteEntity[];
recursiveShare: boolean;
setSharesState(state: SharingStatus): void;
onShareUrlsReady(urls: string[]): void;
}
const getShareLinks = (shares: StateShare[]) => {
const links = [];
for (const share of shares) {
if (!share) {
throw new Error('Error: Empty share.');
}
links.push(ShareService.instance().shareUrl(ShareService.instance().userId, share));
}
return links;
};
const useOnShareLinkClick = ({
setSharesState, onShareUrlsReady, notes, recursiveShare,
}: Props) => {
return useCallback(async () => {
const service = ShareService.instance();
let hasSynced = false;
let tryToSync = false;
while (true) {
try {
if (tryToSync) {
setSharesState(SharingStatus.Synchronizing);
await reg.waitForSyncFinishedThenSync();
tryToSync = false;
hasSynced = true;
}
setSharesState(SharingStatus.Creating);
const newShares: StateShare[] = [];
for (const note of notes) {
const share = await service.shareNote(note.id, recursiveShare);
newShares.push(share);
}
setSharesState(SharingStatus.Synchronizing);
await reg.waitForSyncFinishedThenSync();
setSharesState(SharingStatus.Creating);
onShareUrlsReady(getShareLinks(newShares));
setSharesState(SharingStatus.Created);
await ShareService.instance().refreshShares();
} catch (error) {
if (error.code === 404 && !hasSynced) {
logger.info('ShareNoteDialog: Note does not exist on server - trying to sync it.', error);
tryToSync = true;
continue;
}
console.error(error);
logger.error('ShareNoteDialog: Cannot publish note:', error);
setSharesState(SharingStatus.Idle);
void shim.showErrorDialog(JoplinServerApi.connectionErrorMessage(error));
}
break;
}
}, [recursiveShare, notes, onShareUrlsReady, setSharesState]);
};
export default useOnShareLinkClick;

View File

@@ -0,0 +1,29 @@
import { _, _n } from '../../../locale';
import shim from '../../../shim';
import { SharingStatus } from './types';
interface Props {
sharesState: SharingStatus;
noteCount: number;
}
const useShareStatusMessage = ({ sharesState, noteCount }: Props): string => {
if (sharesState === SharingStatus.Synchronizing) {
return _('Synchronising...');
}
if (sharesState === SharingStatus.Creating) {
return _n('Generating link...', 'Generating links...', noteCount);
}
if (sharesState === SharingStatus.Created) {
// On web, copying text after a long delay (e.g. to sync) fails.
// As such, the web UI for copying links is a bit different:
if (shim.mobilePlatform() === 'web') {
return _n('Link created!', 'Links created!', noteCount);
} else {
return _n('Link has been copied to clipboard!', 'Links have been copied to clipboard!', noteCount);
}
}
return '';
};
export default useShareStatusMessage;