1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00

Mobile: Fixes #11134: Fix automatic resource download mode (#11144)

This commit is contained in:
Henry Heino 2024-10-11 14:14:18 -07:00 committed by GitHub
parent 447e4638d1
commit b61467097d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 70 additions and 13 deletions

View File

@ -7,7 +7,7 @@ import { Provider } from 'react-redux';
import NoteScreen from './Note';
import { MenuProvider } from 'react-native-popup-menu';
import { setupDatabaseAndSynchronizer, switchClient, simulateReadOnlyShareEnv, runWithFakeTimers } from '@joplin/lib/testing/test-utils';
import { setupDatabaseAndSynchronizer, switchClient, simulateReadOnlyShareEnv, supportDir, synchronizerStart, resourceFetcher, runWithFakeTimers } from '@joplin/lib/testing/test-utils';
import { waitFor as waitForWithRealTimers } from '@joplin/lib/testing/test-utils';
import Note from '@joplin/lib/models/Note';
import { AppState } from '../../utils/types';
@ -27,6 +27,8 @@ import { LayoutChangeEvent } from 'react-native';
import shim from '@joplin/lib/shim';
import getWebViewWindowById from '../../utils/testing/getWebViewWindowById';
import CodeMirrorControl from '@joplin/editor/CodeMirror/CodeMirrorControl';
import Setting from '@joplin/lib/models/Setting';
import Resource from '@joplin/lib/models/Resource';
interface WrapperProps {
}
@ -68,11 +70,8 @@ const waitForNoteToMatch = async (noteId: string, note: Partial<NoteEntity>) =>
}));
};
const openNewNote = async (noteProperties: NoteEntity) => {
const note = await Note.save({
parent_id: (await Folder.defaultFolder()).id,
...noteProperties,
});
const openExistingNote = async (noteId: string) => {
const note = await Note.load(noteId);
const displayParentId = getDisplayParentId(note, await Folder.load(note.parent_id));
store.dispatch({
@ -85,7 +84,15 @@ const openNewNote = async (noteProperties: NoteEntity) => {
id: note.id,
folderId: displayParentId,
});
};
const openNewNote = async (noteProperties: NoteEntity) => {
const note = await Note.save({
parent_id: (await Folder.defaultFolder()).id,
...noteProperties,
});
await openExistingNote(note.id);
await waitForNoteToMatch(note.id, { parent_id: note.parent_id, title: note.title, body: note.body });
return note.id;
@ -132,6 +139,7 @@ const openEditor = async () => {
describe('screens/Note', () => {
beforeEach(async () => {
await setupDatabaseAndSynchronizer(1);
await setupDatabaseAndSynchronizer(0);
await switchClient(0);
@ -279,4 +287,48 @@ describe('screens/Note', () => {
cleanup();
});
it.each([
'auto',
'manual',
])('should correctly auto-download or not auto-download resources in %j mode', async (downloadMode) => {
let note = await Note.save({ title: 'Note 1', parent_id: (await Folder.defaultFolder()).id });
note = await shim.attachFileToNote(note, `${supportDir}/photo.jpg`);
await synchronizerStart();
await switchClient(1);
Setting.setValue('sync.resourceDownloadMode', downloadMode);
await synchronizerStart();
// Before opening the note, the resource should not be marked for download
const allResources = await Resource.all();
expect(allResources.length).toBe(1);
const resource = allResources[0];
expect(await Resource.localState(resource)).toMatchObject({ fetch_status: Resource.FETCH_STATUS_IDLE });
await openExistingNote(note.id);
render(<WrappedNoteScreen />);
// Note should render
const titleInput = await screen.findByDisplayValue('Note 1');
expect(titleInput).toBeVisible();
// Wrap in act() -- the component may update in the background during this.
await act(async () => {
await resourceFetcher().waitForAllFinished();
// After opening the note, the resource should be marked for download only in automatic mode
if (downloadMode === 'auto') {
await waitFor(async () => {
expect(await Resource.localState(resource.id)).toMatchObject({ fetch_status: Resource.FETCH_STATUS_DONE });
});
} else if (downloadMode === 'manual') {
// In manual mode, should not mark for download
expect(await Resource.localState(resource)).toMatchObject({ fetch_status: Resource.FETCH_STATUS_IDLE });
} else {
throw new Error(`Should not be testing downloadMode: ${downloadMode}.`);
}
});
});
});

View File

@ -493,11 +493,6 @@ class NoteScreenComponent extends BaseScreenComponent<Props, State> implements B
this.undoRedoService_ = new UndoRedoService();
this.undoRedoService_.on('stackChange', this.undoRedoService_stackChange);
if (this.state.note && this.state.note.body && Setting.value('sync.resourceDownloadMode') === 'auto') {
const resourceIds = await Note.linkedResourceIds(this.state.note.body);
await ResourceFetcher.instance().markForDownload(resourceIds);
}
// Although it is async, we don't wait for the answer so that if permission
// has already been granted, it doesn't slow down opening the note. If it hasn't
// been granted, the popup will open anyway.
@ -509,8 +504,12 @@ class NoteScreenComponent extends BaseScreenComponent<Props, State> implements B
void ResourceFetcher.instance().markForDownload(event.resourceId);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
public componentDidUpdate(prevProps: any, prevState: any) {
public async markAllAttachedResourcesForDownload() {
const resourceIds = await Note.linkedResourceIds(this.state.note.body);
await ResourceFetcher.instance().markForDownload(resourceIds);
}
public componentDidUpdate(prevProps: Props, prevState: State) {
if (this.doFocusUpdate_) {
this.doFocusUpdate_ = false;
this.scheduleFocusUpdate();
@ -528,6 +527,11 @@ class NoteScreenComponent extends BaseScreenComponent<Props, State> implements B
void promptRestoreAutosave((drawingData: string) => {
void this.attachNewDrawing(drawingData);
});
// Handle automatic resource downloading
if (this.state.note?.body && Setting.value('sync.resourceDownloadMode') === 'auto') {
void this.markAllAttachedResourcesForDownload();
}
}
// Disable opening/closing the side menu with touch gestures

View File

@ -286,6 +286,7 @@ async function switchClient(id: number, options: any = null) {
BaseItem.encryptionService_ = encryptionServices_[id];
Resource.encryptionService_ = encryptionServices_[id];
BaseItem.revisionService_ = revisionServices_[id];
ResourceFetcher.instance_ = resourceFetchers_[id];
await Setting.reset();
Setting.settingFilename = settingFilename(id);