feat: vault-aligned server v1 + UX polish
All checks were successful
CI / Windows build (push) Successful in 7m47s
All checks were successful
CI / Windows build (push) Successful in 7m47s
Redesign the optional FastAPI companion around vault files (manifest / PUT/GET/DELETE + OCR jobs) instead of legacy strokes_json notes. Wire a client Server settings panel for health/login. Polish shell UX: l10n for settings/home/board, sticky-board empty state, and a narrow-screen diagnostics FAB. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -199,5 +199,43 @@
|
||||
},
|
||||
"syncAuto": "Sync automatically on launch",
|
||||
"syncCredentialsNote": "Credentials are stored locally in plain text. Use a dedicated app password.",
|
||||
"syncNotConfigured": "Enter a server URL to enable sync."
|
||||
"syncNotConfigured": "Enter a server URL to enable sync.",
|
||||
"settingsDefaults": "Defaults",
|
||||
"settingsAppearance": "Appearance",
|
||||
"settingsAbout": "About",
|
||||
"settingsDefaultTool": "Default tool",
|
||||
"settingsDefaultColor": "Default color",
|
||||
"settingsDefaultWidth": "Default stroke width",
|
||||
"settingsPressureCurve": "Pressure curve",
|
||||
"settingsClearConfirmBody": "This resets pen defaults and appearance. Notes and documents are not affected.",
|
||||
"serverSection": "BadNote Server",
|
||||
"serverUrl": "Server URL",
|
||||
"serverUrlHint": "http://192.168.1.10:8080",
|
||||
"serverUsername": "Username",
|
||||
"serverPassword": "Password",
|
||||
"serverSave": "Save & sign in",
|
||||
"serverTest": "Test connection",
|
||||
"serverTestOk": "Connected · API {version}",
|
||||
"@serverTestOk": {
|
||||
"placeholders": { "version": { "type": "String" } }
|
||||
},
|
||||
"serverTestFail": "Connection failed: {error}",
|
||||
"@serverTestFail": {
|
||||
"placeholders": { "error": { "type": "String" } }
|
||||
},
|
||||
"serverLoggedIn": "Signed in",
|
||||
"serverHint": "Optional. Self-hosted vault assist + deferred OCR; notes stay fully offline.",
|
||||
"boardEmptyTitle": "No sticky notes yet",
|
||||
"boardEmptyBody": "Tap + to add a card. Write [[other-card-id]] in the body to create a backlink.",
|
||||
"relativeJustNow": "Just now",
|
||||
"relativeMinutesAgo": "{n}m ago",
|
||||
"@relativeMinutesAgo": { "placeholders": { "n": { "type": "int" } } },
|
||||
"relativeHoursAgo": "{n}h ago",
|
||||
"@relativeHoursAgo": { "placeholders": { "n": { "type": "int" } } },
|
||||
"relativeYesterday": "Yesterday",
|
||||
"diagExported": "Diagnostic pack exported ({bytes} bytes)\nPath copied",
|
||||
"@diagExported": { "placeholders": { "bytes": { "type": "int" } } },
|
||||
"diagExportFail": "Export failed: {error}",
|
||||
"@diagExportFail": { "placeholders": { "error": { "type": "String" } } },
|
||||
"processingOcr": "Processing OCR…"
|
||||
}
|
||||
|
||||
@@ -985,6 +985,174 @@ abstract class AppLocalizations {
|
||||
/// In en, this message translates to:
|
||||
/// **'Enter a server URL to enable sync.'**
|
||||
String get syncNotConfigured;
|
||||
|
||||
/// No description provided for @settingsDefaults.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Defaults'**
|
||||
String get settingsDefaults;
|
||||
|
||||
/// No description provided for @settingsAppearance.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Appearance'**
|
||||
String get settingsAppearance;
|
||||
|
||||
/// No description provided for @settingsAbout.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'About'**
|
||||
String get settingsAbout;
|
||||
|
||||
/// No description provided for @settingsDefaultTool.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Default tool'**
|
||||
String get settingsDefaultTool;
|
||||
|
||||
/// No description provided for @settingsDefaultColor.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Default color'**
|
||||
String get settingsDefaultColor;
|
||||
|
||||
/// No description provided for @settingsDefaultWidth.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Default stroke width'**
|
||||
String get settingsDefaultWidth;
|
||||
|
||||
/// No description provided for @settingsPressureCurve.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Pressure curve'**
|
||||
String get settingsPressureCurve;
|
||||
|
||||
/// No description provided for @settingsClearConfirmBody.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'This resets pen defaults and appearance. Notes and documents are not affected.'**
|
||||
String get settingsClearConfirmBody;
|
||||
|
||||
/// No description provided for @serverSection.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'BadNote Server'**
|
||||
String get serverSection;
|
||||
|
||||
/// No description provided for @serverUrl.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Server URL'**
|
||||
String get serverUrl;
|
||||
|
||||
/// No description provided for @serverUrlHint.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'http://192.168.1.10:8080'**
|
||||
String get serverUrlHint;
|
||||
|
||||
/// No description provided for @serverUsername.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Username'**
|
||||
String get serverUsername;
|
||||
|
||||
/// No description provided for @serverPassword.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Password'**
|
||||
String get serverPassword;
|
||||
|
||||
/// No description provided for @serverSave.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Save & sign in'**
|
||||
String get serverSave;
|
||||
|
||||
/// No description provided for @serverTest.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Test connection'**
|
||||
String get serverTest;
|
||||
|
||||
/// No description provided for @serverTestOk.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Connected · API {version}'**
|
||||
String serverTestOk(String version);
|
||||
|
||||
/// No description provided for @serverTestFail.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Connection failed: {error}'**
|
||||
String serverTestFail(String error);
|
||||
|
||||
/// No description provided for @serverLoggedIn.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Signed in'**
|
||||
String get serverLoggedIn;
|
||||
|
||||
/// No description provided for @serverHint.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Optional. Self-hosted vault assist + deferred OCR; notes stay fully offline.'**
|
||||
String get serverHint;
|
||||
|
||||
/// No description provided for @boardEmptyTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'No sticky notes yet'**
|
||||
String get boardEmptyTitle;
|
||||
|
||||
/// No description provided for @boardEmptyBody.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Tap + to add a card. Write [[other-card-id]] in the body to create a backlink.'**
|
||||
String get boardEmptyBody;
|
||||
|
||||
/// No description provided for @relativeJustNow.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Just now'**
|
||||
String get relativeJustNow;
|
||||
|
||||
/// No description provided for @relativeMinutesAgo.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{n}m ago'**
|
||||
String relativeMinutesAgo(int n);
|
||||
|
||||
/// No description provided for @relativeHoursAgo.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{n}h ago'**
|
||||
String relativeHoursAgo(int n);
|
||||
|
||||
/// No description provided for @relativeYesterday.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Yesterday'**
|
||||
String get relativeYesterday;
|
||||
|
||||
/// No description provided for @diagExported.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Diagnostic pack exported ({bytes} bytes)\nPath copied'**
|
||||
String diagExported(int bytes);
|
||||
|
||||
/// No description provided for @diagExportFail.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Export failed: {error}'**
|
||||
String diagExportFail(String error);
|
||||
|
||||
/// No description provided for @processingOcr.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Processing OCR…'**
|
||||
String get processingOcr;
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate
|
||||
|
||||
@@ -489,4 +489,103 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get syncNotConfigured => 'Enter a server URL to enable sync.';
|
||||
|
||||
@override
|
||||
String get settingsDefaults => 'Defaults';
|
||||
|
||||
@override
|
||||
String get settingsAppearance => 'Appearance';
|
||||
|
||||
@override
|
||||
String get settingsAbout => 'About';
|
||||
|
||||
@override
|
||||
String get settingsDefaultTool => 'Default tool';
|
||||
|
||||
@override
|
||||
String get settingsDefaultColor => 'Default color';
|
||||
|
||||
@override
|
||||
String get settingsDefaultWidth => 'Default stroke width';
|
||||
|
||||
@override
|
||||
String get settingsPressureCurve => 'Pressure curve';
|
||||
|
||||
@override
|
||||
String get settingsClearConfirmBody =>
|
||||
'This resets pen defaults and appearance. Notes and documents are not affected.';
|
||||
|
||||
@override
|
||||
String get serverSection => 'BadNote Server';
|
||||
|
||||
@override
|
||||
String get serverUrl => 'Server URL';
|
||||
|
||||
@override
|
||||
String get serverUrlHint => 'http://192.168.1.10:8080';
|
||||
|
||||
@override
|
||||
String get serverUsername => 'Username';
|
||||
|
||||
@override
|
||||
String get serverPassword => 'Password';
|
||||
|
||||
@override
|
||||
String get serverSave => 'Save & sign in';
|
||||
|
||||
@override
|
||||
String get serverTest => 'Test connection';
|
||||
|
||||
@override
|
||||
String serverTestOk(String version) {
|
||||
return 'Connected · API $version';
|
||||
}
|
||||
|
||||
@override
|
||||
String serverTestFail(String error) {
|
||||
return 'Connection failed: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get serverLoggedIn => 'Signed in';
|
||||
|
||||
@override
|
||||
String get serverHint =>
|
||||
'Optional. Self-hosted vault assist + deferred OCR; notes stay fully offline.';
|
||||
|
||||
@override
|
||||
String get boardEmptyTitle => 'No sticky notes yet';
|
||||
|
||||
@override
|
||||
String get boardEmptyBody =>
|
||||
'Tap + to add a card. Write [[other-card-id]] in the body to create a backlink.';
|
||||
|
||||
@override
|
||||
String get relativeJustNow => 'Just now';
|
||||
|
||||
@override
|
||||
String relativeMinutesAgo(int n) {
|
||||
return '${n}m ago';
|
||||
}
|
||||
|
||||
@override
|
||||
String relativeHoursAgo(int n) {
|
||||
return '${n}h ago';
|
||||
}
|
||||
|
||||
@override
|
||||
String get relativeYesterday => 'Yesterday';
|
||||
|
||||
@override
|
||||
String diagExported(int bytes) {
|
||||
return 'Diagnostic pack exported ($bytes bytes)\nPath copied';
|
||||
}
|
||||
|
||||
@override
|
||||
String diagExportFail(String error) {
|
||||
return 'Export failed: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get processingOcr => 'Processing OCR…';
|
||||
}
|
||||
|
||||
@@ -484,4 +484,100 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get syncNotConfigured => '请输入服务器地址以启用同步。';
|
||||
|
||||
@override
|
||||
String get settingsDefaults => '默认笔迹';
|
||||
|
||||
@override
|
||||
String get settingsAppearance => '外观';
|
||||
|
||||
@override
|
||||
String get settingsAbout => '关于';
|
||||
|
||||
@override
|
||||
String get settingsDefaultTool => '默认工具';
|
||||
|
||||
@override
|
||||
String get settingsDefaultColor => '默认颜色';
|
||||
|
||||
@override
|
||||
String get settingsDefaultWidth => '默认线宽';
|
||||
|
||||
@override
|
||||
String get settingsPressureCurve => '压感曲线';
|
||||
|
||||
@override
|
||||
String get settingsClearConfirmBody => '将重置笔默认值与外观设置。笔记和文档不会受影响。';
|
||||
|
||||
@override
|
||||
String get serverSection => 'BadNote 服务器';
|
||||
|
||||
@override
|
||||
String get serverUrl => '服务器地址';
|
||||
|
||||
@override
|
||||
String get serverUrlHint => 'http://192.168.1.10:8080';
|
||||
|
||||
@override
|
||||
String get serverUsername => '用户名';
|
||||
|
||||
@override
|
||||
String get serverPassword => '密码';
|
||||
|
||||
@override
|
||||
String get serverSave => '保存并登录';
|
||||
|
||||
@override
|
||||
String get serverTest => '测试连接';
|
||||
|
||||
@override
|
||||
String serverTestOk(String version) {
|
||||
return '连接成功 · API $version';
|
||||
}
|
||||
|
||||
@override
|
||||
String serverTestFail(String error) {
|
||||
return '连接失败:$error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get serverLoggedIn => '已登录';
|
||||
|
||||
@override
|
||||
String get serverHint => '可选。用于自托管 vault 协助同步与延迟 OCR;日常笔记仍完全离线。';
|
||||
|
||||
@override
|
||||
String get boardEmptyTitle => '还没有便利贴';
|
||||
|
||||
@override
|
||||
String get boardEmptyBody => '点按右下角添加卡片。在正文写 [[另一张卡片id]] 可建立双链。';
|
||||
|
||||
@override
|
||||
String get relativeJustNow => '刚刚';
|
||||
|
||||
@override
|
||||
String relativeMinutesAgo(int n) {
|
||||
return '$n 分钟前';
|
||||
}
|
||||
|
||||
@override
|
||||
String relativeHoursAgo(int n) {
|
||||
return '$n 小时前';
|
||||
}
|
||||
|
||||
@override
|
||||
String get relativeYesterday => '昨天';
|
||||
|
||||
@override
|
||||
String diagExported(int bytes) {
|
||||
return '诊断包已导出($bytes 字节)\n路径已复制';
|
||||
}
|
||||
|
||||
@override
|
||||
String diagExportFail(String error) {
|
||||
return '导出失败:$error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get processingOcr => '正在识别文字…';
|
||||
}
|
||||
|
||||
@@ -169,5 +169,43 @@
|
||||
},
|
||||
"syncAuto": "启动时自动同步",
|
||||
"syncCredentialsNote": "凭据以明文保存在本地,建议使用专用的应用密码。",
|
||||
"syncNotConfigured": "请输入服务器地址以启用同步。"
|
||||
"syncNotConfigured": "请输入服务器地址以启用同步。",
|
||||
"settingsDefaults": "默认笔迹",
|
||||
"settingsAppearance": "外观",
|
||||
"settingsAbout": "关于",
|
||||
"settingsDefaultTool": "默认工具",
|
||||
"settingsDefaultColor": "默认颜色",
|
||||
"settingsDefaultWidth": "默认线宽",
|
||||
"settingsPressureCurve": "压感曲线",
|
||||
"settingsClearConfirmBody": "将重置笔默认值与外观设置。笔记和文档不会受影响。",
|
||||
"serverSection": "BadNote 服务器",
|
||||
"serverUrl": "服务器地址",
|
||||
"serverUrlHint": "http://192.168.1.10:8080",
|
||||
"serverUsername": "用户名",
|
||||
"serverPassword": "密码",
|
||||
"serverSave": "保存并登录",
|
||||
"serverTest": "测试连接",
|
||||
"serverTestOk": "连接成功 · API {version}",
|
||||
"@serverTestOk": {
|
||||
"placeholders": { "version": { "type": "String" } }
|
||||
},
|
||||
"serverTestFail": "连接失败:{error}",
|
||||
"@serverTestFail": {
|
||||
"placeholders": { "error": { "type": "String" } }
|
||||
},
|
||||
"serverLoggedIn": "已登录",
|
||||
"serverHint": "可选。用于自托管 vault 协助同步与延迟 OCR;日常笔记仍完全离线。",
|
||||
"boardEmptyTitle": "还没有便利贴",
|
||||
"boardEmptyBody": "点按右下角添加卡片。在正文写 [[另一张卡片id]] 可建立双链。",
|
||||
"relativeJustNow": "刚刚",
|
||||
"relativeMinutesAgo": "{n} 分钟前",
|
||||
"@relativeMinutesAgo": { "placeholders": { "n": { "type": "int" } } },
|
||||
"relativeHoursAgo": "{n} 小时前",
|
||||
"@relativeHoursAgo": { "placeholders": { "n": { "type": "int" } } },
|
||||
"relativeYesterday": "昨天",
|
||||
"diagExported": "诊断包已导出({bytes} 字节)\n路径已复制",
|
||||
"@diagExported": { "placeholders": { "bytes": { "type": "int" } } },
|
||||
"diagExportFail": "导出失败:{error}",
|
||||
"@diagExportFail": { "placeholders": { "error": { "type": "String" } } },
|
||||
"processingOcr": "正在识别文字…"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user