Web: Add welcome notes specific to the web app (#14499)

This commit is contained in:
Henry Heino
2026-03-03 07:30:03 -08:00
committed by GitHub
parent 766ef933b9
commit af706ac1b3
6 changed files with 77 additions and 9 deletions

View File

@@ -1,7 +1,8 @@
import { setupDatabaseAndSynchronizer, switchClient } from './testing/test-utils';
import WelcomeUtils from './WelcomeUtils';
import WelcomeUtils, { WelcomeAssetPlatform } from './WelcomeUtils';
import Folder from './models/Folder';
import { FolderIconType } from './services/database/types';
import Note from './models/Note';
describe('WelcomeUtils', () => {
@@ -11,7 +12,7 @@ describe('WelcomeUtils', () => {
});
it('should create welcome items with waving hand emoji icon for the folder', async () => {
const result = await WelcomeUtils.createWelcomeItems('en_GB');
const result = await WelcomeUtils.createWelcomeItems('en_GB', WelcomeAssetPlatform.Desktop);
expect(result.defaultFolderId).toBeTruthy();
@@ -23,4 +24,21 @@ describe('WelcomeUtils', () => {
expect(icon.emoji).toBe('👋');
});
it.each([
WelcomeAssetPlatform.Web, WelcomeAssetPlatform.Desktop,
])('should create web welcome notes only on web (testing platform: %s)', async (platform) => {
const result = await WelcomeUtils.createWelcomeItems('en_GB', platform);
const notes = await Note.previews(result.defaultFolderId);
const webAppNoteTitle = '0. About the web app';
const noteTitles = notes.map(note => note.title);
if (platform === WelcomeAssetPlatform.Web) {
expect(noteTitles).toContain(webAppNoteTitle);
} else {
expect(noteTitles).not.toContain(webAppNoteTitle);
}
});
});

View File

@@ -2,15 +2,23 @@ const welcomeAssetsAny = require('./welcomeAssets');
import Note from './models/Note';
import Setting from './models/Setting';
import Folder from './models/Folder';
import shim from './shim';
import shim, { MobilePlatform } from './shim';
import uuid from './uuid';
import { fileExtension, basename } from './path-utils';
import { _ } from './locale';
const { pregQuote } = require('./string-utils');
import { FolderIconType } from './services/database/types';
export enum WelcomeAssetPlatform {
Desktop = 'desktop',
Cli = 'cli',
Mobile = 'mobile',
Web = 'web',
}
export interface ItemMetadatum {
id: string;
platform?: WelcomeAssetPlatform;
}
export type ItemMetadata = Record<string, ItemMetadatum>;
@@ -30,6 +38,7 @@ export interface WelcomeAssetNote {
title: string;
body: string;
resources: Record<string, WelcomeAssetResource>;
platform?: WelcomeAssetPlatform;
}
export interface WelcomeAssetFolder {
@@ -47,7 +56,7 @@ export type WelcomeAssets = Record<string, AssetContent>;
class WelcomeUtils {
public static async createWelcomeItems(locale: string): Promise<CreateWelcomeItemsResult> {
public static async createWelcomeItems(locale: string, platform: WelcomeAssetPlatform): Promise<CreateWelcomeItemsResult> {
const output: CreateWelcomeItemsResult = {
defaultFolderId: null,
};
@@ -80,6 +89,10 @@ class WelcomeUtils {
const noteAsset = noteAssets[i];
const enGbNoteAsset = enGbWelcomeAssets.notes[i];
if (noteAsset.platform && noteAsset.platform !== platform) {
continue;
}
let noteBody = noteAsset.body;
for (const resourceUrl in enGbNoteAsset.resources) {
@@ -109,6 +122,18 @@ class WelcomeUtils {
return output;
}
private static detectPlatform_() {
if (shim.mobilePlatform() === MobilePlatform.Web) {
return WelcomeAssetPlatform.Web;
} else if (shim.mobilePlatform()) {
return WelcomeAssetPlatform.Mobile;
} else if (shim.isElectron()) {
return WelcomeAssetPlatform.Desktop;
} else {
return WelcomeAssetPlatform.Cli;
}
}
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
public static async install(locale: string, dispatch: Function) {
if (!Setting.value('welcome.enabled')) {
@@ -117,7 +142,7 @@ class WelcomeUtils {
}
if (!Setting.value('welcome.wasBuilt')) {
const result = await WelcomeUtils.createWelcomeItems(locale);
const result = await WelcomeUtils.createWelcomeItems(locale, this.detectPlatform_());
Setting.setValue('welcome.wasBuilt', true);
dispatch({

View File

@@ -4,7 +4,7 @@ import { syncTargetName, afterAllCleanUp, synchronizerStart, setupDatabaseAndSyn
import Folder from '../../models/Folder';
import Note from '../../models/Note';
import BaseItem from '../../models/BaseItem';
import WelcomeUtils from '../../WelcomeUtils';
import WelcomeUtils, { WelcomeAssetPlatform } from '../../WelcomeUtils';
import { NoteEntity } from '../database/types';
import { fetchSyncInfo, setAppMinVersion, uploadSyncInfo } from './syncInfoUtils';
import { ErrorCode } from '../../errors';
@@ -355,12 +355,12 @@ describe('Synchronizer.basics', () => {
it('should create a new Welcome notebook on each client', (async () => {
// Create the Welcome items on two separate clients
await WelcomeUtils.createWelcomeItems('en_GB');
await WelcomeUtils.createWelcomeItems('en_GB', WelcomeAssetPlatform.Cli);
await synchronizerStart();
await switchClient(2);
await WelcomeUtils.createWelcomeItems('en_GB');
await WelcomeUtils.createWelcomeItems('en_GB', WelcomeAssetPlatform.Cli);
const beforeFolderCount = (await Folder.all()).length;
const beforeNoteCount = (await Note.all()).length;
expect(beforeFolderCount === 1).toBe(true);

View File

@@ -1,6 +1,14 @@
module.exports = {
"en_GB": {
"notes": [
{
"id": "4ec2e7505fc2e7505ec2e7505ec2a751",
"platform": "web",
"title": "0. About the web app",
"body": "# About the web app\n\nThe web app provides access to Joplin from a web browser.\n\nLike the desktop and mobile apps, the web app is local-first. Notes and attachments are stored locally on your computer, but can optionally be synced to the cloud.\n",
"resources": {},
"parent_id": "9bb5d498aba74cc6a047cfdc841e82a1"
},
{
"id": "8a1556e382704160808e9a7bef7135d3",
"title": "1. Welcome to Joplin!",

View File

@@ -2,7 +2,7 @@ import { readFileSync, readdirSync, writeFileSync } from 'fs-extra';
import { dirname } from 'path';
import { fileExtension, basename } from '@joplin/lib/path-utils';
import markdownUtils from '@joplin/lib/markdownUtils';
import { AssetContent, ItemMetadata, WelcomeAssetNote, WelcomeAssetResource, WelcomeAssets } from '@joplin/lib/WelcomeUtils';
import { AssetContent, ItemMetadata, WelcomeAssetNote, WelcomeAssetPlatform, WelcomeAssetResource, WelcomeAssets } from '@joplin/lib/WelcomeUtils';
const rootDir = dirname(dirname(__dirname));
const enWelcomeDir = `${rootDir}/readme/welcome`;
@@ -10,6 +10,10 @@ const enWelcomeDir = `${rootDir}/readme/welcome`;
const createdDate = new Date('2018-06-22T12:00:00Z');
const itemMetadata_: ItemMetadata = {
'0_web.md': {
id: '4ec2e7505fc2e7505ec2e7505ec2a751',
platform: WelcomeAssetPlatform.Web,
},
'1_welcome_to_joplin.md': {
id: '8a1556e382704160808e9a7bef7135d3',
},
@@ -81,6 +85,10 @@ function itemIdFromPath(metadata: ItemMetadata, path: string) {
return md.id;
}
function itemPlatformFromPath(metadata: ItemMetadata, path: string) {
return itemMetadata(metadata, path).platform;
}
function fileToBase64(filePath: string) {
const content = readFileSync(filePath);
return Buffer.from(content).toString('base64');
@@ -110,6 +118,7 @@ function parseNoteFile(metadata: ItemMetadata, locale: string, filePath: string)
return {
id: itemIdFromPath(metadata, filePath),
platform: itemPlatformFromPath(metadata, filePath),
title: title,
body: body,
resources: resources,

8
readme/welcome/0_web.md Normal file
View File

@@ -0,0 +1,8 @@
# About the web app
The web app provides access to Joplin from a web browser.
Like the desktop and mobile apps, the web app is local-first:
- Notes and attachments are stored locally on your computer. Changes are saved even if offline.
- [Synchronisation](https://joplinapp.org/help/apps/sync/) needs to be enabled/configured to sync data to the cloud.
- Until synchronisation is configured, each different browser/profile will have a different note collection.