Merge branch 'release/3.8.0'

This commit is contained in:
Karol Sójko
2021-06-08 16:14:51 +02:00
16 changed files with 62 additions and 29 deletions

View File

@@ -11,9 +11,11 @@ APP_HOST=http://localhost:3001
EXTENSIONS_MANAGER_LOCATION=extensions/extensions-manager/dist/index.html EXTENSIONS_MANAGER_LOCATION=extensions/extensions-manager/dist/index.html
BATCH_MANAGER_LOCATION=extensions/batch-manager/dist/index.min.html BATCH_MANAGER_LOCATION=extensions/batch-manager/dist/index.min.html
SF_DEFAULT_SERVER=http://localhost:3000 SF_DEFAULT_SERVER=http://localhost:3000
SF_NEXT_VERSION_SERVER=http://localhost:3000
# Development options # Development options
DEV_DEFAULT_SYNC_SERVER=https://sync.standardnotes.org DEV_DEFAULT_SYNC_SERVER=https://sync.standardnotes.org
DEV_NEXT_VERSION_SYNC_SERVER=https://api.standardnotes.com
DEV_EXTENSIONS_MANAGER_LOCATION=public/extensions/extensions-manager/dist/index.html DEV_EXTENSIONS_MANAGER_LOCATION=public/extensions/extensions-manager/dist/index.html
DEV_BATCH_MANAGER_LOCATION=public/extensions/batch-manager/dist/index.min.html DEV_BATCH_MANAGER_LOCATION=public/extensions/batch-manager/dist/index.min.html

View File

@@ -108,10 +108,13 @@ The web app makes use of two optional native extensions, which, when running the
BATCH_MANAGER_LOCATION=extensions/batch-manager/dist/index.min.html BATCH_MANAGER_LOCATION=extensions/batch-manager/dist/index.min.html
``` ```
You can also set the `SF_DEFAULT_SERVER` environment variable to set the default server for login and registration. You can also set the `SF_DEFAULT_SERVER` and `SF_NEXT_VERSION_SERVER` environment variables to set the default servers for login and registration.
> **Note:** SF_NEXT_VERSION_SERVER can point to the same server. It is used for gradual upgrade of API versions.
``` ```
SF_DEFAULT_SERVER=https://sync.myserver SF_DEFAULT_SERVER=https://sync.myserver
SF_NEXT_VERSION_SERVER=https://sync.myserver
``` ```
--- ---

View File

@@ -88,7 +88,8 @@ function reloadHiddenFirefoxTab(): boolean {
const startApplication: StartApplication = async function startApplication( const startApplication: StartApplication = async function startApplication(
defaultSyncServerHost: string, defaultSyncServerHost: string,
bridge: Bridge bridge: Bridge,
nextVersionSyncServerHost: string,
) { ) {
if (reloadHiddenFirefoxTab()) { if (reloadHiddenFirefoxTab()) {
return; return;
@@ -105,6 +106,7 @@ const startApplication: StartApplication = async function startApplication(
.config(configRoutes) .config(configRoutes)
.constant('bridge', bridge) .constant('bridge', bridge)
.constant('defaultSyncServerHost', defaultSyncServerHost) .constant('defaultSyncServerHost', defaultSyncServerHost)
.constant('nextVersionSyncServerHost', nextVersionSyncServerHost)
.constant('appVersion', bridge.appVersion); .constant('appVersion', bridge.appVersion);
// Controllers // Controllers
@@ -186,7 +188,8 @@ const startApplication: StartApplication = async function startApplication(
if (__WEB__) { if (__WEB__) {
startApplication( startApplication(
(window as any)._default_sync_server, (window as any)._default_sync_server,
new BrowserBridge(__VERSION__) new BrowserBridge(__VERSION__),
(window as any)._next_version_sync_server
); );
} else { } else {
(window as any).startApplication = startApplication; (window as any).startApplication = startApplication;

View File

@@ -72,11 +72,11 @@ export const NotesOptions = observer(
const buttonRect = tagsButtonRef.current.getBoundingClientRect(); const buttonRect = tagsButtonRef.current.getBoundingClientRect();
const footerHeight = 32; const footerHeight = 32;
if ((buttonRect.top + maxTagsMenuSize) > (clientHeight - footerHeight)) { if (buttonRect.top + maxTagsMenuSize > clientHeight - footerHeight) {
setTagsMenuMaxHeight(clientHeight - buttonRect.top - footerHeight - 2); setTagsMenuMaxHeight(clientHeight - buttonRect.top - footerHeight - 2);
} }
if ((buttonRect.right + maxTagsMenuSize) > clientWidth) { if (buttonRect.right + maxTagsMenuSize > clientWidth) {
setTagsMenuPosition({ setTagsMenuPosition({
top: buttonRect.top, top: buttonRect.top,
right: clientWidth - buttonRect.left, right: clientWidth - buttonRect.left,
@@ -88,7 +88,6 @@ export const NotesOptions = observer(
}); });
} }
setTagsMenuOpen(!tagsMenuOpen); setTagsMenuOpen(!tagsMenuOpen);
}; };
@@ -169,7 +168,7 @@ export const NotesOptions = observer(
{appState.tags.tags.map((tag) => ( {appState.tags.tags.map((tag) => (
<button <button
key={tag.title} key={tag.title}
className={`${buttonClass} py-2`} className={`${buttonClass} py-2 max-w-80`}
onBlur={closeOnBlur} onBlur={closeOnBlur}
onClick={() => { onClick={() => {
appState.notes.isTagInSelectedNotes(tag) appState.notes.isTagInSelectedNotes(tag)
@@ -178,11 +177,12 @@ export const NotesOptions = observer(
}} }}
> >
<span <span
className={ className={`whitespace-nowrap overflow-hidden overflow-ellipsis
appState.notes.isTagInSelectedNotes(tag) ${
? 'font-bold' appState.notes.isTagInSelectedNotes(tag)
: '' ? 'font-bold'
} : ''
}`}
> >
{tag.title} {tag.title}
</span> </span>

View File

@@ -2,5 +2,6 @@ import { Bridge } from "./services/bridge";
export type StartApplication = ( export type StartApplication = (
defaultSyncServerHost: string, defaultSyncServerHost: string,
bridge: Bridge bridge: Bridge,
nextVersionSyncServerHost: string
) => Promise<void>; ) => Promise<void>;

View File

@@ -108,13 +108,14 @@ export class NotesState {
} }
} }
async selectNote(uuid: UuidString): Promise<void> { async selectNote(uuid: UuidString, userTriggered?: boolean): Promise<void> {
const note = this.application.findItem(uuid) as SNNote; const note = this.application.findItem(uuid) as SNNote;
if (note) { if (note) {
if ( if (
this.io.activeModifiers.has(KeyboardModifier.Meta) || userTriggered &&
this.io.activeModifiers.has(KeyboardModifier.Ctrl) (this.io.activeModifiers.has(KeyboardModifier.Meta) ||
this.io.activeModifiers.has(KeyboardModifier.Ctrl))
) { ) {
if (this.selectedNotes[uuid]) { if (this.selectedNotes[uuid]) {
delete this.selectedNotes[uuid]; delete this.selectedNotes[uuid];
@@ -124,7 +125,10 @@ export class NotesState {
this.lastSelectedNote = note; this.lastSelectedNote = note;
}); });
} }
} else if (this.io.activeModifiers.has(KeyboardModifier.Shift)) { } else if (
userTriggered &&
this.io.activeModifiers.has(KeyboardModifier.Shift)
) {
await this.selectNotesRange(note); await this.selectNotesRange(note);
} else { } else {
const shouldSelectNote = const shouldSelectNote =

View File

@@ -53,6 +53,7 @@ export class WebApplication extends SNApplication {
scope: angular.IScope, scope: angular.IScope,
defaultSyncServerHost: string, defaultSyncServerHost: string,
public bridge: Bridge, public bridge: Bridge,
nextVersionSyncServerHost: string,
) { ) {
super( super(
bridge.environment, bridge.environment,
@@ -62,7 +63,8 @@ export class WebApplication extends SNApplication {
new AlertService(), new AlertService(),
identifier, identifier,
[], [],
defaultSyncServerHost defaultSyncServerHost,
nextVersionSyncServerHost,
); );
this.$compile = $compile; this.$compile = $compile;
this.scope = scope; this.scope = scope;

View File

@@ -28,7 +28,8 @@ export class ApplicationGroup extends SNApplicationGroup {
$rootScope: ng.IRootScopeService, $rootScope: ng.IRootScopeService,
$timeout: ng.ITimeoutService, $timeout: ng.ITimeoutService,
private defaultSyncServerHost: string, private defaultSyncServerHost: string,
private bridge: Bridge private bridge: Bridge,
private nextVersionSyncServerHost: string,
) { ) {
super(new WebDeviceInterface($timeout, bridge)); super(new WebDeviceInterface($timeout, bridge));
this.$compile = $compile; this.$compile = $compile;
@@ -62,7 +63,8 @@ export class ApplicationGroup extends SNApplicationGroup {
this.$compile, this.$compile,
scope, scope,
this.defaultSyncServerHost, this.defaultSyncServerHost,
this.bridge this.bridge,
this.nextVersionSyncServerHost,
); );
const appState = new AppState( const appState = new AppState(
this.$rootScope, this.$rootScope,

View File

@@ -130,7 +130,7 @@
ng-attr-id='note-{{note.uuid}}' ng-attr-id='note-{{note.uuid}}'
ng-repeat='note in self.state.renderedNotes track by note.uuid' ng-repeat='note in self.state.renderedNotes track by note.uuid'
ng-class="{'selected' : self.isNoteSelected(note.uuid) }" ng-class="{'selected' : self.isNoteSelected(note.uuid) }"
ng-click='self.selectNote(note)' ng-click='self.selectNote(note, true)'
) )
.note-flags(ng-show='self.noteFlags[note.uuid].length > 0') .note-flags(ng-show='self.noteFlags[note.uuid].length > 0')
.flag(ng-class='flag.class', ng-repeat='flag in self.noteFlags[note.uuid]') .flag(ng-class='flag.class', ng-repeat='flag in self.noteFlags[note.uuid]')

View File

@@ -305,7 +305,7 @@ class NotesViewCtrl extends PureViewCtrl<unknown, NotesCtrlState> {
private async openNotesContextMenu(e: MouseEvent, note: SNNote) { private async openNotesContextMenu(e: MouseEvent, note: SNNote) {
e.preventDefault(); e.preventDefault();
if (!this.state.selectedNotes[note.uuid]) { if (!this.state.selectedNotes[note.uuid]) {
await this.selectNote(note); await this.selectNote(note, true);
} }
if (this.state.selectedNotes[note.uuid]) { if (this.state.selectedNotes[note.uuid]) {
const { clientHeight } = document.documentElement; const { clientHeight } = document.documentElement;
@@ -395,8 +395,8 @@ class NotesViewCtrl extends PureViewCtrl<unknown, NotesCtrlState> {
} }
} }
async selectNote(note: SNNote): Promise<void> { async selectNote(note: SNNote, userTriggered?: boolean): Promise<void> {
await this.appState.notes.selectNote(note.uuid); await this.appState.notes.selectNote(note.uuid, userTriggered);
} }
async createNewNote() { async createNewNote() {

View File

@@ -171,6 +171,18 @@
align-items: flex-start; align-items: flex-start;
} }
.whitespace-nowrap {
white-space: nowrap;
}
.overflow-hidden {
overflow: hidden;
}
.overflow-ellipsis {
text-overflow: ellipsis;
}
/** /**
* A button that is just an icon. Separated from .sn-button because there * A button that is just an icon. Separated from .sn-button because there
* is almost no style overlap. * is almost no style overlap.

View File

@@ -15,6 +15,7 @@
.sk-panel-row .sk-panel-row
p.sk-p p.sk-p
| Extensions use an offline messaging system to communicate. Learn more at | Extensions use an offline messaging system to communicate. Learn more at
|
a.sk-a.info( a.sk-a.info(
href='https://standardnotes.org/permissions', href='https://standardnotes.org/permissions',
rel='noopener', rel='noopener',

View File

@@ -30,6 +30,7 @@
<script> <script>
window._default_sync_server = "<%= ENV['SF_DEFAULT_SERVER'] %>"; window._default_sync_server = "<%= ENV['SF_DEFAULT_SERVER'] %>";
window._next_version_sync_server = "<%= ENV['SF_NEXT_VERSION_SERVER'] %>";
window._extensions_manager_location = "<%= ENV['EXTENSIONS_MANAGER_LOCATION'] %>"; window._extensions_manager_location = "<%= ENV['EXTENSIONS_MANAGER_LOCATION'] %>";
window._batch_manager_location = "<%= ENV['BATCH_MANAGER_LOCATION'] %>"; window._batch_manager_location = "<%= ENV['BATCH_MANAGER_LOCATION'] %>";
window._bugsnag_api_key = "<%= ENV['BUGSNAG_API_KEY'] %>"; window._bugsnag_api_key = "<%= ENV['BUGSNAG_API_KEY'] %>";

View File

@@ -30,12 +30,14 @@
<body <body
data-default-sync-server="<%= env.DEV_DEFAULT_SYNC_SERVER %>" data-default-sync-server="<%= env.DEV_DEFAULT_SYNC_SERVER %>"
data-next-version-sync-server="<%= env.DEV_NEXT_VERSION_SYNC_SERVER %>"
data-extensions-manager-location="<%= env.DEV_EXTENSIONS_MANAGER_LOCATION %>" data-extensions-manager-location="<%= env.DEV_EXTENSIONS_MANAGER_LOCATION %>"
data-batch-manager-location="<%= env.DEV_BATCH_MANAGER_LOCATION %>" data-batch-manager-location="<%= env.DEV_BATCH_MANAGER_LOCATION %>"
data-bugsnag-api-key="<%= env.DEV_BUGSNAG_API_KEY %>" data-bugsnag-api-key="<%= env.DEV_BUGSNAG_API_KEY %>"
> >
<script> <script>
window._default_sync_server = document.body.dataset.defaultSyncServer || "https://sync.standardnotes.org"; window._default_sync_server = document.body.dataset.defaultSyncServer || "https://sync.standardnotes.org";
window._next_version_sync_server = document.body.dataset.nextVersionSyncServer || "https://api.standardnotes.com";
window._extensions_manager_location = document.body.dataset.extensionsManagerLocation || "public/extensions/extensions-manager/dist/index.html"; window._extensions_manager_location = document.body.dataset.extensionsManagerLocation || "public/extensions/extensions-manager/dist/index.html";
window._batch_manager_location = document.body.dataset.batchManagerLocation || "public/extensions/batch-manager/dist/index.min.html"; window._batch_manager_location = document.body.dataset.batchManagerLocation || "public/extensions/batch-manager/dist/index.min.html";
window._bugsnag_api_key = document.body.dataset.bugsnagApiKey; window._bugsnag_api_key = document.body.dataset.bugsnagApiKey;

View File

@@ -71,7 +71,7 @@
"@reach/checkbox": "^0.13.2", "@reach/checkbox": "^0.13.2",
"@reach/dialog": "^0.13.0", "@reach/dialog": "^0.13.0",
"@standardnotes/sncrypto-web": "1.2.10", "@standardnotes/sncrypto-web": "1.2.10",
"@standardnotes/snjs": "2.4.2", "@standardnotes/snjs": "2.5.0",
"mobx": "^6.1.6", "mobx": "^6.1.6",
"mobx-react-lite": "^3.2.0", "mobx-react-lite": "^3.2.0",
"preact": "^10.5.12" "preact": "^10.5.12"

View File

@@ -1936,10 +1936,10 @@
"@standardnotes/sncrypto-common" "^1.2.7" "@standardnotes/sncrypto-common" "^1.2.7"
libsodium-wrappers "^0.7.8" libsodium-wrappers "^0.7.8"
"@standardnotes/snjs@2.4.2": "@standardnotes/snjs@2.5.0":
version "2.4.2" version "2.5.0"
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.4.2.tgz#5d3dfd6ae5f40984e0d28b776684561b5818eadf" resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.5.0.tgz#fcd45f8c6884fcc204633be33366b59ede71c5b1"
integrity sha512-/R8Lsbo9NqQ2FZKe4N4V4ZQxUbfmzU5jA6FtW0wE+g6c5MtHPO9fRoWK81PJXumc+t9VI8q2nswkthyqIGgEgA== integrity sha512-VWThoZhymoCOqRkZjXj3vDhQGAPMt+KUrB/FyYZkl+9jVCMX6NIGziLb8fThFaZzoyC/qp5BuoceZlbyrggOnw==
dependencies: dependencies:
"@standardnotes/auth" "^2.0.0" "@standardnotes/auth" "^2.0.0"
"@standardnotes/sncrypto-common" "^1.2.9" "@standardnotes/sncrypto-common" "^1.2.9"