feat: display warning banner when using the app with no account
This commit is contained in:
@@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<!--
|
||||
2019-4-11: Created with FontForge (http://fontforge.org)
|
||||
-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
|
||||
<metadata>
|
||||
Created by FontForge 20190318 at Thu Apr 11 10:47:26 2019
|
||||
By Mo Bitar
|
||||
Copyright (c) 2019, Mo Bitar
|
||||
</metadata>
|
||||
<defs>
|
||||
<font id="Ionicons" horiz-adv-x="384" >
|
||||
<font-face
|
||||
font-family="Ionicons"
|
||||
font-weight="400"
|
||||
font-stretch="normal"
|
||||
units-per-em="512"
|
||||
panose-1="2 0 5 9 0 0 0 0 0 0"
|
||||
ascent="448"
|
||||
descent="-64"
|
||||
bbox="0 -32 384 416"
|
||||
underline-thickness="25.6"
|
||||
underline-position="-51.2"
|
||||
unicode-range="U+F200-F266"
|
||||
/>
|
||||
<missing-glyph />
|
||||
<glyph glyph-name="ion-arrow-return-right" unicode=""
|
||||
d="M384 256l-128 -96v64h-192v-128h248c4 0 8 -4 8 -8v-48c0 -4 -4 -8 -8 -8h-304c-4 0 -8 4 -8 8v240c0 4 4 8 8 8h248v64z" />
|
||||
<glyph glyph-name="ion-arrow-return-left" unicode=""
|
||||
d="M128 352v-64h248c4 0 8 -4 8 -8v-240c0 -4 -4 -8 -8 -8h-304c-4 0 -8 4 -8 8v48c0 4 4 8 8 8h248v128h-192v-64l-128 96z" />
|
||||
<glyph glyph-name="ion-plus" unicode=""
|
||||
d="M384 224v-64h-160v-160h-64v160h-160v64h160v160h64v-160h160z" />
|
||||
<glyph glyph-name="ion-locked" unicode=""
|
||||
d="M22 -32c-12 0 -22 10 -22 22v212c0 12 10 22 22 22h3h19v31c0 42 17 87 43 115s64 46 105 46v0v0c41 0 79 -18 105 -46s43 -73 43 -115v-31h22c12 0 22 -10 22 -22v-212c0 -12 -10 -22 -22 -22h-340zM97 255v-31h17h155h18v31c0 27 -10 61 -28 80v0v1
|
||||
c-18 19 -42 29 -67 29v0v0c-25 0 -49 -10 -67 -29v-1v0c-18 -19 -28 -53 -28 -80z" />
|
||||
</font>
|
||||
</defs></svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
3
app/assets/icons/ic_close.svg
Normal file
3
app/assets/icons/ic_close.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.2457 1.92913C11.5701 1.60466 11.5701 1.07859 11.2457 0.754126C10.9212 0.429659 10.3951 0.429659 10.0707 0.754126L5.99984 4.82496L1.929 0.754126C1.60454 0.429659 1.07847 0.429659 0.754004 0.754126C0.429537 1.07859 0.429537 1.60466 0.754004 1.92913L4.82484 5.99996L0.754004 10.0708C0.429537 10.3953 0.429537 10.9213 0.754004 11.2458C1.07847 11.5703 1.60454 11.5703 1.929 11.2458L5.99984 7.17496L10.0707 11.2458C10.3951 11.5703 10.9212 11.5703 11.2457 11.2458C11.5701 10.9213 11.5701 10.3953 11.2457 10.0708L7.17484 5.99996L11.2457 1.92913Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 657 B |
3
app/assets/javascripts/@types/modules.ts
Normal file
3
app/assets/javascripts/@types/modules.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
declare module '*.svg' {
|
||||
export default function SvgComponent(props: React.SVGProps<SVGSVGElement>): JSX.Element;
|
||||
}
|
||||
@@ -55,7 +55,8 @@ import { BrowserBridge } from './services/browserBridge';
|
||||
import { startErrorReporting } from './services/errorReporting';
|
||||
import { StartApplication } from './startApplication';
|
||||
import { Bridge } from './services/bridge';
|
||||
import { SessionsModalDirective } from './directives/views/sessionsModal';
|
||||
import { SessionsModalDirective } from './components/SessionsModal';
|
||||
import { NoAccountWarningDirective } from './components/NoAccountWarning';
|
||||
|
||||
|
||||
function reloadHiddenFirefoxTab(): boolean {
|
||||
@@ -141,7 +142,8 @@ const startApplication: StartApplication = async function startApplication(
|
||||
.directive('revisionPreviewModal', () => new RevisionPreviewModal())
|
||||
.directive('historyMenu', () => new HistoryMenu())
|
||||
.directive('syncResolutionMenu', () => new SyncResolutionMenu())
|
||||
.directive('sessionsModal', SessionsModalDirective);
|
||||
.directive('sessionsModal', SessionsModalDirective)
|
||||
.directive('noAccountWarning', NoAccountWarningDirective);
|
||||
|
||||
// Filters
|
||||
angular.module('app').filter('trusted', ['$sce', trusted]);
|
||||
|
||||
46
app/assets/javascripts/components/NoAccountWarning.tsx
Normal file
46
app/assets/javascripts/components/NoAccountWarning.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import { WebApplication } from '@/ui_models/application';
|
||||
import { toDirective, useAutorunValue } from './utils';
|
||||
import Close from '../../icons/ic_close.svg';
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
|
||||
function NoAccountWarning({
|
||||
application,
|
||||
appState,
|
||||
}: {
|
||||
application: WebApplication;
|
||||
appState: AppState;
|
||||
}) {
|
||||
const canShow = useAutorunValue(() => appState.noAccountWarning.show);
|
||||
if (!canShow || application.hasAccount()) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div className="mt-5 p-5 rounded-md shadow-sm grid grid-template-cols-1fr">
|
||||
<h1 className="sk-h3 m-0 font-semibold">Data not backed up</h1>
|
||||
<p className="m-0 mt-1 col-start-1 col-end-3">
|
||||
Sign in or register to back up your notes
|
||||
</p>
|
||||
<button
|
||||
className="sn-btn mt-3 col-start-1 col-end-3 justify-self-start"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
appState.accountMenu.setShow(true);
|
||||
}}
|
||||
>
|
||||
Open Account menu
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
appState.noAccountWarning.hide();
|
||||
}}
|
||||
title="Ignore"
|
||||
label="Ignore"
|
||||
className="border-0 p-0 bg-transparent cursor-pointer rounded-md col-start-2 row-start-1"
|
||||
>
|
||||
<Close className="fill-neutral hover:fill-info" />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const NoAccountWarningDirective = toDirective(NoAccountWarning);
|
||||
@@ -1,14 +1,12 @@
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
import { PureViewCtrl } from '@/views';
|
||||
import {
|
||||
SNApplication,
|
||||
RemoteSession,
|
||||
SessionStrings,
|
||||
UuidString,
|
||||
isNullOrUndefined,
|
||||
RemoteSession,
|
||||
} from '@standardnotes/snjs';
|
||||
import { autorun, IAutorunOptions, IReactionPublic } from 'mobx';
|
||||
import { render, FunctionComponent } from 'preact';
|
||||
import { FunctionComponent } from 'preact';
|
||||
import { useState, useEffect, useRef, useMemo } from 'preact/hooks';
|
||||
import { Dialog } from '@reach/dialog';
|
||||
import { Alert } from '@reach/alert';
|
||||
@@ -17,13 +15,8 @@ import {
|
||||
AlertDialogDescription,
|
||||
AlertDialogLabel,
|
||||
} from '@reach/alert-dialog';
|
||||
|
||||
function useAutorun(
|
||||
view: (r: IReactionPublic) => unknown,
|
||||
opts?: IAutorunOptions
|
||||
) {
|
||||
useEffect(() => autorun(view, opts), [view, opts]);
|
||||
}
|
||||
import { toDirective, useAutorun } from './utils';
|
||||
import { WebApplication } from '@/ui_models/application';
|
||||
|
||||
type Session = RemoteSession & {
|
||||
revoking?: true;
|
||||
@@ -250,7 +243,7 @@ const SessionsModal: FunctionComponent<{
|
||||
|
||||
const Sessions: FunctionComponent<{
|
||||
appState: AppState;
|
||||
application: SNApplication;
|
||||
application: WebApplication;
|
||||
}> = ({ appState, application }) => {
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
useAutorun(() => setShowModal(appState.isSessionsModalVisible));
|
||||
@@ -262,27 +255,4 @@ const Sessions: FunctionComponent<{
|
||||
}
|
||||
};
|
||||
|
||||
class SessionsModalCtrl extends PureViewCtrl<unknown, unknown> {
|
||||
/* @ngInject */
|
||||
constructor(private $element: JQLite, $timeout: ng.ITimeoutService) {
|
||||
super($timeout);
|
||||
this.$element = $element;
|
||||
}
|
||||
$onChanges() {
|
||||
render(
|
||||
<Sessions appState={this.appState} application={this.application} />,
|
||||
this.$element[0]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
export function SessionsModalDirective() {
|
||||
return {
|
||||
controller: SessionsModalCtrl,
|
||||
bindToController: true,
|
||||
scope: {
|
||||
application: '=',
|
||||
},
|
||||
};
|
||||
}
|
||||
export const SessionsModalDirective = toDirective(Sessions);
|
||||
56
app/assets/javascripts/components/utils.ts
Normal file
56
app/assets/javascripts/components/utils.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { WebApplication } from '@/ui_models/application';
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
import { autorun, IAutorunOptions, IReactionPublic } from 'mobx';
|
||||
import { FunctionComponent, h, render } from 'preact';
|
||||
import { useEffect } from 'preact/hooks';
|
||||
import { useState } from 'react';
|
||||
|
||||
export function useAutorunValue<T>(query: () => T): T {
|
||||
const [value, setValue] = useState(query);
|
||||
useAutorun(() => {
|
||||
setValue(query());
|
||||
});
|
||||
return value;
|
||||
}
|
||||
|
||||
export function useAutorun(
|
||||
view: (r: IReactionPublic) => unknown,
|
||||
opts?: IAutorunOptions
|
||||
): void {
|
||||
useEffect(() => autorun(view, opts), [view, opts]);
|
||||
}
|
||||
|
||||
export function toDirective(
|
||||
component: FunctionComponent<{
|
||||
application: WebApplication;
|
||||
appState: AppState;
|
||||
}>
|
||||
) {
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
return function () {
|
||||
return {
|
||||
controller: [
|
||||
'$element',
|
||||
'$scope',
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
($element: JQLite, $scope: any) => {
|
||||
return {
|
||||
$onChanges() {
|
||||
render(
|
||||
h(component, {
|
||||
application: $scope.application,
|
||||
appState: $scope.appState,
|
||||
}),
|
||||
$element[0]
|
||||
);
|
||||
},
|
||||
};
|
||||
},
|
||||
],
|
||||
scope: {
|
||||
application: '=',
|
||||
appState: '=',
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -75,7 +75,7 @@ export class DesktopManager extends ApplicationService {
|
||||
|
||||
getExtServerHost() {
|
||||
console.assert(
|
||||
this.bridge.extensionsServerHost,
|
||||
!!this.bridge.extensionsServerHost,
|
||||
'extServerHost is null'
|
||||
);
|
||||
return this.bridge.extensionsServerHost;
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
export enum StorageKey {
|
||||
DisableErrorReporting = 'DisableErrorReporting',
|
||||
AnonymousUserId = 'AnonymousUserId',
|
||||
ShowBetaWarning = 'ShowBetaWarning',
|
||||
ShowNoAccountWarning = 'ShowNoAccountWarning',
|
||||
}
|
||||
|
||||
export type StorageValue = {
|
||||
[StorageKey.DisableErrorReporting]: boolean;
|
||||
[StorageKey.AnonymousUserId]: string;
|
||||
[StorageKey.ShowBetaWarning]: boolean;
|
||||
[StorageKey.ShowNoAccountWarning]: boolean;
|
||||
}
|
||||
|
||||
export const storage = {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"allowJs": true,
|
||||
"noEmit": true,
|
||||
"strict": true,
|
||||
"isolatedModules": true,
|
||||
"isolatedModules": false,
|
||||
"esModuleInterop": true,
|
||||
"declaration": true,
|
||||
"newLine": "lf",
|
||||
@@ -14,6 +14,7 @@
|
||||
"baseUrl": ".",
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "preact",
|
||||
"typeRoots": ["./@types"],
|
||||
"paths": {
|
||||
"%/*": ["../templates/*"],
|
||||
"@/*": ["./*"],
|
||||
|
||||
@@ -15,6 +15,7 @@ import { WebApplication } from '@/ui_models/application';
|
||||
import { Editor } from '@/ui_models/editor';
|
||||
import { action, makeObservable, observable } from 'mobx';
|
||||
import { Bridge } from '@/services/bridge';
|
||||
import { storage, StorageKey } from '@/services/localStorage';
|
||||
|
||||
export enum AppStateEvent {
|
||||
TagChanged,
|
||||
@@ -30,7 +31,7 @@ export enum AppStateEvent {
|
||||
export type PanelResizedData = {
|
||||
panel: string;
|
||||
collapsed: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
export enum EventSource {
|
||||
UserInteraction,
|
||||
@@ -39,8 +40,6 @@ export enum EventSource {
|
||||
|
||||
type ObserverCallback = (event: AppStateEvent, data?: any) => Promise<void>;
|
||||
|
||||
const SHOW_BETA_WARNING_KEY = 'show_beta_warning';
|
||||
|
||||
class ActionsMenuState {
|
||||
hiddenExtensions: Record<UuidString, boolean> = {};
|
||||
|
||||
@@ -75,7 +74,7 @@ export class SyncState {
|
||||
});
|
||||
}
|
||||
|
||||
update(status: SyncOpStatus) {
|
||||
update(status: SyncOpStatus): void {
|
||||
this.errorMessage = status.error?.message;
|
||||
this.inProgress = status.syncInProgress;
|
||||
const stats = status.getStats();
|
||||
@@ -95,6 +94,41 @@ export class SyncState {
|
||||
}
|
||||
}
|
||||
|
||||
class AccountMenuState {
|
||||
show = false;
|
||||
constructor() {
|
||||
makeObservable(this, {
|
||||
show: observable,
|
||||
setShow: action,
|
||||
toggleShow: action,
|
||||
});
|
||||
}
|
||||
setShow(show: boolean) {
|
||||
this.show = show;
|
||||
}
|
||||
toggleShow() {
|
||||
this.show = !this.show;
|
||||
}
|
||||
}
|
||||
|
||||
class NoAccountWarningState {
|
||||
show: boolean;
|
||||
constructor() {
|
||||
this.show = storage.get(StorageKey.ShowNoAccountWarning) ?? true;
|
||||
makeObservable(this, {
|
||||
show: observable,
|
||||
hide: action,
|
||||
});
|
||||
}
|
||||
hide() {
|
||||
this.show = false;
|
||||
storage.set(StorageKey.ShowNoAccountWarning, false);
|
||||
}
|
||||
reset() {
|
||||
storage.remove(StorageKey.ShowNoAccountWarning);
|
||||
}
|
||||
}
|
||||
|
||||
export class AppState {
|
||||
readonly enableUnfinishedFeatures =
|
||||
isDev || location.host.includes('app-dev.standardnotes.org');
|
||||
@@ -109,8 +143,10 @@ export class AppState {
|
||||
rootScopeCleanup2: any;
|
||||
onVisibilityChange: any;
|
||||
selectedTag?: SNTag;
|
||||
showBetaWarning = false;
|
||||
showBetaWarning: boolean;
|
||||
readonly accountMenu = new AccountMenuState();
|
||||
readonly actionsMenu = new ActionsMenuState();
|
||||
readonly noAccountWarning = new NoAccountWarningState();
|
||||
readonly sync = new SyncState();
|
||||
isSessionsModalVisible = false;
|
||||
|
||||
@@ -124,15 +160,6 @@ export class AppState {
|
||||
this.$timeout = $timeout;
|
||||
this.$rootScope = $rootScope;
|
||||
this.application = application;
|
||||
makeObservable(this, {
|
||||
showBetaWarning: observable,
|
||||
isSessionsModalVisible: observable,
|
||||
|
||||
enableBetaWarning: action,
|
||||
disableBetaWarning: action,
|
||||
openSessionsModal: action,
|
||||
closeSessionsModal: action,
|
||||
});
|
||||
this.addAppEventObserver();
|
||||
this.streamNotesAndTags();
|
||||
this.onVisibilityChange = () => {
|
||||
@@ -143,12 +170,28 @@ export class AppState {
|
||||
this.notifyEvent(event);
|
||||
};
|
||||
this.registerVisibilityObservers();
|
||||
this.determineBetaWarningValue();
|
||||
|
||||
if (this.bridge.appVersion.includes('-beta')) {
|
||||
this.showBetaWarning = storage.get(StorageKey.ShowBetaWarning) ?? true;
|
||||
} else {
|
||||
this.showBetaWarning = false;
|
||||
}
|
||||
|
||||
makeObservable(this, {
|
||||
showBetaWarning: observable,
|
||||
isSessionsModalVisible: observable,
|
||||
|
||||
enableBetaWarning: action,
|
||||
disableBetaWarning: action,
|
||||
openSessionsModal: action,
|
||||
closeSessionsModal: action,
|
||||
});
|
||||
}
|
||||
|
||||
deinit(source: DeinitSource) {
|
||||
deinit(source: DeinitSource): void {
|
||||
if (source === DeinitSource.SignOut) {
|
||||
localStorage.removeItem(SHOW_BETA_WARNING_KEY);
|
||||
storage.remove(StorageKey.ShowBetaWarning);
|
||||
this.noAccountWarning.reset();
|
||||
}
|
||||
this.actionsMenu.deinit();
|
||||
this.unsubApp();
|
||||
@@ -174,30 +217,12 @@ export class AppState {
|
||||
|
||||
disableBetaWarning() {
|
||||
this.showBetaWarning = false;
|
||||
localStorage.setItem(SHOW_BETA_WARNING_KEY, 'false');
|
||||
storage.set(StorageKey.ShowBetaWarning, false);
|
||||
}
|
||||
|
||||
enableBetaWarning() {
|
||||
this.showBetaWarning = true;
|
||||
localStorage.setItem(SHOW_BETA_WARNING_KEY, 'true');
|
||||
}
|
||||
|
||||
clearBetaWarning() {
|
||||
localStorage.setItem(SHOW_BETA_WARNING_KEY, 'true');
|
||||
}
|
||||
|
||||
private determineBetaWarningValue() {
|
||||
if (this.bridge.appVersion.includes('-beta')) {
|
||||
switch (localStorage.getItem(SHOW_BETA_WARNING_KEY)) {
|
||||
case 'true':
|
||||
default:
|
||||
this.enableBetaWarning();
|
||||
break;
|
||||
case 'false':
|
||||
this.disableBetaWarning();
|
||||
break;
|
||||
}
|
||||
}
|
||||
storage.set(StorageKey.ShowBetaWarning, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
declare const process : {
|
||||
env: {
|
||||
NODE_ENV: string | null | undefined
|
||||
}
|
||||
};
|
||||
|
||||
export const isDev = process.env.NODE_ENV === 'development';
|
||||
|
||||
export function getPlatformString() {
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
path(d="M480 256l-75.53-33.53L256.1 290.6l-148.77-68.17L32 256l224 102 224-102z")
|
||||
sessions-modal(
|
||||
application='self.application'
|
||||
app-state='self.appState'
|
||||
)
|
||||
challenge-modal(
|
||||
ng-repeat="challenge in self.challenges track by challenge.id"
|
||||
|
||||
@@ -62,7 +62,7 @@ class FooterViewCtrl extends PureViewCtrl<unknown, {
|
||||
public arbitraryStatusMessage?: string
|
||||
public user?: any
|
||||
private offline = true
|
||||
private showAccountMenu = false
|
||||
public showAccountMenu = false
|
||||
private didCheckForOffline = false
|
||||
private queueExtReload = false
|
||||
private reloadInProgress = false
|
||||
@@ -75,7 +75,7 @@ class FooterViewCtrl extends PureViewCtrl<unknown, {
|
||||
private observerRemovers: Array<() => void> = [];
|
||||
private completedInitialSync = false;
|
||||
private showingDownloadStatus = false;
|
||||
private removeBetaWarningListener?: IReactionDisposer;
|
||||
private autorunDisposer?: IReactionDisposer;
|
||||
|
||||
/* @ngInject */
|
||||
constructor(
|
||||
@@ -103,7 +103,7 @@ class FooterViewCtrl extends PureViewCtrl<unknown, {
|
||||
this.rootScopeListener2 = undefined;
|
||||
(this.closeAccountMenu as any) = undefined;
|
||||
(this.toggleSyncResolutionMenu as any) = undefined;
|
||||
this.removeBetaWarningListener?.();
|
||||
this.autorunDisposer?.();
|
||||
super.deinit();
|
||||
}
|
||||
|
||||
@@ -115,8 +115,9 @@ class FooterViewCtrl extends PureViewCtrl<unknown, {
|
||||
});
|
||||
});
|
||||
this.loadAccountSwitcherState();
|
||||
this.removeBetaWarningListener = autorun(() => {
|
||||
this.autorunDisposer = autorun(() => {
|
||||
const showBetaWarning = this.appState.showBetaWarning;
|
||||
this.showAccountMenu = this.appState.accountMenu.show;
|
||||
this.setState({
|
||||
showBetaWarning: showBetaWarning,
|
||||
showDataUpgrade: !showBetaWarning
|
||||
@@ -255,7 +256,7 @@ class FooterViewCtrl extends PureViewCtrl<unknown, {
|
||||
if (!this.didCheckForOffline) {
|
||||
this.didCheckForOffline = true;
|
||||
if (this.offline && this.application.getNoteCount() === 0) {
|
||||
this.showAccountMenu = true;
|
||||
this.appState.accountMenu.setShow(true);
|
||||
}
|
||||
}
|
||||
this.syncUpdated();
|
||||
@@ -437,7 +438,7 @@ class FooterViewCtrl extends PureViewCtrl<unknown, {
|
||||
}
|
||||
|
||||
accountMenuPressed() {
|
||||
this.showAccountMenu = !this.showAccountMenu;
|
||||
this.appState.accountMenu.toggleShow();
|
||||
this.closeAllRooms();
|
||||
}
|
||||
|
||||
@@ -446,7 +447,7 @@ class FooterViewCtrl extends PureViewCtrl<unknown, {
|
||||
}
|
||||
|
||||
closeAccountMenu() {
|
||||
this.showAccountMenu = false;
|
||||
this.appState.accountMenu.setShow(false);
|
||||
}
|
||||
|
||||
lockApp() {
|
||||
@@ -563,7 +564,7 @@ class FooterViewCtrl extends PureViewCtrl<unknown, {
|
||||
if (this.application && this.application.authenticationInProgress()) {
|
||||
return;
|
||||
}
|
||||
this.showAccountMenu = false;
|
||||
this.appState.accountMenu.setShow(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#notes-title-bar.section-title-bar
|
||||
.padded
|
||||
.section-title-bar-header
|
||||
.title {{self.state.panelTitle}}
|
||||
.sk-h2.font-semibold.title {{self.state.panelTitle}}
|
||||
.sk-button.contrast.wide(
|
||||
ng-click='self.createNewNote()',
|
||||
title='Create a new note in the selected tag'
|
||||
@@ -24,6 +24,10 @@
|
||||
ng-click='self.clearFilterText();',
|
||||
ng-show='self.state.noteFilter.text'
|
||||
) ✕
|
||||
no-account-warning(
|
||||
application='self.application'
|
||||
app-state='self.appState'
|
||||
)
|
||||
#notes-menu-bar.sn-component
|
||||
.sk-app-bar.no-edges
|
||||
.left
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
.tag-info
|
||||
.title(ng-if="!tag.errorDecrypting") {{tag.title}}
|
||||
.count(ng-show='tag.isAllTag') {{self.state.noteCounts[tag.uuid]}}
|
||||
.danger.small-text.bold(ng-show='tag.conflictOf') Conflicted Copy
|
||||
.danger.small-text.bold(ng-show='tag.errorDecrypting && !tag.waitingForKey') Missing Keys
|
||||
.info.small-text.bold(ng-show='tag.errorDecrypting && tag.waitingForKey') Waiting For Keys
|
||||
.danger.small-text.font-bold(ng-show='tag.conflictOf') Conflicted Copy
|
||||
.danger.small-text.font-bold(ng-show='tag.errorDecrypting && !tag.waitingForKey') Missing Keys
|
||||
.info.small-text.font-bold(ng-show='tag.errorDecrypting && tag.waitingForKey') Waiting For Keys
|
||||
.tags-title-section.section-title-bar
|
||||
.section-title-bar-header
|
||||
.sk-h3.title
|
||||
@@ -52,9 +52,9 @@
|
||||
spellcheck='false'
|
||||
)
|
||||
.count {{self.state.noteCounts[tag.uuid]}}
|
||||
.danger.small-text.bold(ng-show='tag.conflictOf') Conflicted Copy
|
||||
.danger.small-text.bold(ng-show='tag.errorDecrypting && !tag.waitingForKey') Missing Keys
|
||||
.info.small-text.bold(ng-show='tag.errorDecrypting && tag.waitingForKey') Waiting For Keys
|
||||
.danger.small-text.font-bold(ng-show='tag.conflictOf') Conflicted Copy
|
||||
.danger.small-text.font-bold(ng-show='tag.errorDecrypting && !tag.waitingForKey') Missing Keys
|
||||
.info.small-text.font-bold(ng-show='tag.errorDecrypting && tag.waitingForKey') Waiting For Keys
|
||||
.menu(ng-show='self.state.selectedTag == tag')
|
||||
a.item(ng-click='self.selectedRenameTag(tag)' ng-show='!self.state.editingTag') Rename
|
||||
a.item(ng-click='self.saveTag($event, tag)' ng-show='self.state.editingTag') Save
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
src: url('../fonts/ionicons.eot?v=2.0.0');
|
||||
src: url('../fonts/ionicons.eot?v=2.0.1#iefix') format('embedded-opentype'),
|
||||
url('../fonts/ionicons.ttf?v=2.0.1') format('truetype'),
|
||||
url('../fonts/ionicons.woff?v=2.0.1') format('woff'),
|
||||
url('../fonts/ionicons.svg?v=2.0.1#Ionicons') format('svg');
|
||||
url('../fonts/ionicons.woff?v=2.0.1') format('woff');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@@ -30,13 +30,14 @@
|
||||
#notes-title-bar {
|
||||
padding-top: 16px;
|
||||
font-weight: normal;
|
||||
font-size: var(--sn-stylekit-font-size-h1);
|
||||
|
||||
.section-title-bar-header .title {
|
||||
font-size: var(--sn-stylekit-font-size-h3);
|
||||
font-weight: 600;
|
||||
width: calc(90% - 45px);
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: var(--sn-stylekit-font-size-p);
|
||||
}
|
||||
}
|
||||
|
||||
#notes-menu-bar {
|
||||
@@ -80,7 +81,8 @@
|
||||
line-height: 17px;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
right: 8px;
|
||||
|
||||
transition: background-color 0.15s linear;
|
||||
|
||||
14
app/assets/stylesheets/_sn.scss
Normal file
14
app/assets/stylesheets/_sn.scss
Normal file
@@ -0,0 +1,14 @@
|
||||
/* Generic UI controls that have yet to be extracted in Stylekit */
|
||||
|
||||
.sn-btn {
|
||||
@extend .text-sm;
|
||||
@extend .font-bold;
|
||||
@extend .py-2;
|
||||
@extend .px-3;
|
||||
@extend .bg-main;
|
||||
@extend .text-info-contrast;
|
||||
@extend .border-0;
|
||||
@extend .rounded;
|
||||
@extend .cursor-pointer;
|
||||
@extend .hover\:brightness-130;
|
||||
}
|
||||
@@ -57,35 +57,6 @@ $screen-md-max: ($screen-lg-min - 1) !default;
|
||||
}
|
||||
}
|
||||
|
||||
.selectable {
|
||||
user-select: text !important;
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.mt-5 {
|
||||
margin-top: 5px !important;
|
||||
}
|
||||
|
||||
.mt-10 {
|
||||
margin-top: 10px !important;
|
||||
}
|
||||
|
||||
.mr-5 {
|
||||
margin-right: 5px !important;
|
||||
}
|
||||
|
||||
.mr-8 {
|
||||
margin-right: 8px !important;
|
||||
}
|
||||
|
||||
.faded {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.center-align {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.block {
|
||||
display: block !important;
|
||||
}
|
||||
@@ -94,19 +65,6 @@ $screen-md-max: ($screen-lg-min - 1) !default;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.wrap {
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.medium-padding {
|
||||
padding: 10px !important;
|
||||
}
|
||||
|
||||
.bold {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
.normal {
|
||||
font-weight: normal !important;
|
||||
}
|
||||
@@ -118,3 +76,137 @@ $screen-md-max: ($screen-lg-min - 1) !default;
|
||||
.medium-text {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
.faded {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.flex-column {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.self-start {
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.justify-self-start {
|
||||
justify-self: flex-start;
|
||||
}
|
||||
|
||||
.m-0 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.mt-1 {
|
||||
margin-top: .25rem;
|
||||
}
|
||||
.mt-3 {
|
||||
margin-top: .75rem;
|
||||
}
|
||||
.mt-5 {
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
|
||||
.p-5 {
|
||||
padding: 1.25rem;
|
||||
}
|
||||
|
||||
.px-3 {
|
||||
padding-left: .75rem;
|
||||
padding-right: .75rem;
|
||||
}
|
||||
|
||||
.py-2 {
|
||||
padding-top: .5rem;
|
||||
padding-bottom: .5rem;
|
||||
}
|
||||
|
||||
.border-0 {
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
.rounded {
|
||||
border-radius: var(--sn-stylekit-general-border-radius);
|
||||
}
|
||||
.rounded-md {
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.bg-main {
|
||||
background-color: var(--sn-stylekit-info-color);
|
||||
}
|
||||
.bg-transparent {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.col-start-1 {
|
||||
grid-column-start: 1;
|
||||
}
|
||||
.col-start-2 {
|
||||
grid-column-start: 2;
|
||||
}
|
||||
.col-end-3 {
|
||||
grid-column-end: 3;
|
||||
}
|
||||
|
||||
.hover\:brightness-130:hover {
|
||||
filter: brightness(130%);
|
||||
}
|
||||
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fill-neutral {
|
||||
fill: var(--sn-stylekit-neutral-color);
|
||||
}
|
||||
.hover\:fill-info:hover {
|
||||
fill: var(--sn-stylekit-info-color)
|
||||
}
|
||||
|
||||
.font-semibold {
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700 !important;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
}
|
||||
.grid-template-cols-1fr {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.relative {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.row-start-1 {
|
||||
grid-row-start: 1;
|
||||
}
|
||||
|
||||
.selectable {
|
||||
user-select: text !important;
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.shadow-sm {
|
||||
box-shadow: 0px 2px 8px 0px rgba(0, 0, 0, 0.04), 0px 1px 4px 0px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.text-sm {
|
||||
font-size: var(--sn-stylekit-font-size-h5);;
|
||||
}
|
||||
.text-info-contrast {
|
||||
color: var(--sn-stylekit-info-contrast-color);
|
||||
}
|
||||
|
||||
.wrap {
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
@@ -11,3 +11,4 @@
|
||||
@import "ionicons";
|
||||
@import "reach-sub";
|
||||
@import "sessions-modal";
|
||||
@import "sn";
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
.sk-notification-title.sk-panel-row.padded-row Advanced Options
|
||||
.bordered-row.padded-row
|
||||
label.sk-label Sync Server Domain
|
||||
input.sk-input.mt-5.sk-base(
|
||||
input.sk-input.sk-base(
|
||||
name='server',
|
||||
ng-model='self.state.formData.url',
|
||||
ng-change='self.onHostInputChange()'
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
| {{ctrl.permissionsString}}
|
||||
.sk-panel-row
|
||||
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(
|
||||
href='https://standardnotes.org/permissions',
|
||||
rel='noopener',
|
||||
href='https://standardnotes.org/permissions',
|
||||
rel='noopener',
|
||||
target='_blank'
|
||||
) https://standardnotes.org/permissions.
|
||||
.sk-panel-footer
|
||||
.sk-button.info.big.block.bold(ng-click='ctrl.accept()')
|
||||
.sk-button.info.big.block.font-bold(ng-click='ctrl.accept()')
|
||||
.sk-label Continue
|
||||
|
||||
Reference in New Issue
Block a user