Merge branch 'release/10.12.0'
This commit is contained in:
112
Gemfile.lock
112
Gemfile.lock
@@ -43,44 +43,45 @@ GEM
|
||||
arel (8.0.0)
|
||||
bindex (0.8.1)
|
||||
builder (3.2.4)
|
||||
byebug (11.1.1)
|
||||
capistrano (3.11.2)
|
||||
byebug (11.1.3)
|
||||
capistrano (3.16.0)
|
||||
airbrussh (>= 1.0.0)
|
||||
i18n
|
||||
rake (>= 10.0.0)
|
||||
sshkit (>= 1.9.0)
|
||||
capistrano-bundler (1.6.0)
|
||||
capistrano-bundler (2.0.1)
|
||||
capistrano (~> 3.1)
|
||||
capistrano-git-with-submodules (2.0.3)
|
||||
capistrano-git-with-submodules (2.0.4)
|
||||
capistrano (~> 3.7)
|
||||
capistrano-passenger (0.2.0)
|
||||
capistrano-passenger (0.2.1)
|
||||
capistrano (~> 3.0)
|
||||
capistrano-rails (1.4.0)
|
||||
capistrano-rails (1.6.1)
|
||||
capistrano (~> 3.1)
|
||||
capistrano-bundler (~> 1.1)
|
||||
capistrano-bundler (>= 1.1, < 3)
|
||||
capistrano-rvm (0.1.2)
|
||||
capistrano (~> 3.0)
|
||||
sshkit (~> 1.2)
|
||||
capistrano-sidekiq (1.0.3)
|
||||
capistrano-sidekiq (2.0.0)
|
||||
capistrano (>= 3.9.0)
|
||||
sidekiq (>= 3.4, < 6.0)
|
||||
concurrent-ruby (1.1.5)
|
||||
connection_pool (2.2.2)
|
||||
capistrano-bundler
|
||||
sidekiq (>= 6.0)
|
||||
concurrent-ruby (1.1.9)
|
||||
connection_pool (2.2.5)
|
||||
crass (1.0.6)
|
||||
dotenv (2.7.5)
|
||||
dotenv-rails (2.7.5)
|
||||
dotenv (= 2.7.5)
|
||||
railties (>= 3.2, < 6.1)
|
||||
erubi (1.9.0)
|
||||
execjs (2.7.0)
|
||||
ffi (1.12.1)
|
||||
ffi (1.12.1-x64-mingw32)
|
||||
globalid (0.4.2)
|
||||
activesupport (>= 4.2.0)
|
||||
haml (5.1.2)
|
||||
dotenv (2.7.6)
|
||||
dotenv-rails (2.7.6)
|
||||
dotenv (= 2.7.6)
|
||||
railties (>= 3.2)
|
||||
erubi (1.10.0)
|
||||
execjs (2.8.1)
|
||||
ffi (1.15.5)
|
||||
ffi (1.15.5-x64-mingw32)
|
||||
globalid (1.0.0)
|
||||
activesupport (>= 5.0)
|
||||
haml (5.2.2)
|
||||
temple (>= 0.8.0)
|
||||
tilt
|
||||
i18n (1.8.2)
|
||||
i18n (1.10.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
json (1.8.6)
|
||||
lograge (0.11.2)
|
||||
@@ -88,37 +89,31 @@ GEM
|
||||
activesupport (>= 4)
|
||||
railties (>= 4)
|
||||
request_store (~> 1.0)
|
||||
loofah (2.4.0)
|
||||
loofah (2.14.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.7.1)
|
||||
mini_mime (>= 0.1.1)
|
||||
method_source (0.9.2)
|
||||
mini_mime (1.0.2)
|
||||
mini_portile2 (2.5.0)
|
||||
minitest (5.14.0)
|
||||
net-scp (2.0.0)
|
||||
net-ssh (>= 2.6.5, < 6.0.0)
|
||||
net-ssh (5.2.0)
|
||||
newrelic_rpm (7.0.0)
|
||||
method_source (1.0.0)
|
||||
mini_mime (1.1.2)
|
||||
minitest (5.15.0)
|
||||
net-scp (3.0.0)
|
||||
net-ssh (>= 2.6.5, < 7.0.0)
|
||||
net-ssh (6.1.0)
|
||||
newrelic_rpm (7.2.0)
|
||||
nio4r (2.5.8)
|
||||
nokogiri (1.11.1)
|
||||
mini_portile2 (~> 2.5.0)
|
||||
nokogiri (1.13.1-x64-mingw32)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.11.1-x64-mingw32)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.11.1-x86_64-darwin)
|
||||
nokogiri (1.13.1-x86_64-darwin)
|
||||
racc (~> 1.4)
|
||||
non-stupid-digest-assets (1.0.9)
|
||||
sprockets (>= 2.0)
|
||||
puma (4.3.9)
|
||||
puma (5.6.2)
|
||||
nio4r (~> 2.0)
|
||||
racc (1.5.2)
|
||||
racc (1.6.0)
|
||||
rack (2.2.3)
|
||||
rack-cors (1.1.1)
|
||||
rack (>= 2.0.0)
|
||||
rack-protection (2.0.8.1)
|
||||
rack
|
||||
rack-test (1.1.0)
|
||||
rack (>= 1.0, < 3)
|
||||
rails (5.1.7)
|
||||
@@ -136,7 +131,7 @@ GEM
|
||||
rails-dom-testing (2.0.3)
|
||||
activesupport (>= 4.2.0)
|
||||
nokogiri (>= 1.6)
|
||||
rails-html-sanitizer (1.3.0)
|
||||
rails-html-sanitizer (1.4.2)
|
||||
loofah (~> 2.3)
|
||||
railties (5.1.7)
|
||||
actionpack (= 5.1.7)
|
||||
@@ -144,13 +139,13 @@ GEM
|
||||
method_source
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rake (13.0.1)
|
||||
rb-fsevent (0.10.3)
|
||||
rake (13.0.6)
|
||||
rb-fsevent (0.11.1)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
rdoc (4.3.0)
|
||||
redis (4.1.3)
|
||||
request_store (1.5.0)
|
||||
redis (4.6.0)
|
||||
request_store (1.5.1)
|
||||
rack (>= 1.4)
|
||||
responders (2.4.1)
|
||||
actionpack (>= 4.2.0, < 6.0)
|
||||
@@ -163,30 +158,29 @@ GEM
|
||||
sdoc (0.4.2)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
rdoc (~> 4.0)
|
||||
secure_headers (6.3.0)
|
||||
sidekiq (5.2.7)
|
||||
connection_pool (~> 2.2, >= 2.2.2)
|
||||
rack (>= 1.5.0)
|
||||
rack-protection (>= 1.5.0)
|
||||
redis (>= 3.3.5, < 5)
|
||||
spring (2.1.0)
|
||||
sprockets (4.0.0)
|
||||
secure_headers (6.3.3)
|
||||
sidekiq (6.4.1)
|
||||
connection_pool (>= 2.2.2)
|
||||
rack (~> 2.0)
|
||||
redis (>= 4.2.0)
|
||||
spring (3.1.1)
|
||||
sprockets (4.0.2)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (> 1, < 3)
|
||||
sprockets-rails (3.2.1)
|
||||
sprockets-rails (3.2.2)
|
||||
actionpack (>= 4.0)
|
||||
activesupport (>= 4.0)
|
||||
sprockets (>= 3.0.0)
|
||||
sshkit (1.20.0)
|
||||
sshkit (1.21.2)
|
||||
net-scp (>= 1.1.2)
|
||||
net-ssh (>= 2.8.0)
|
||||
temple (0.8.2)
|
||||
thor (1.0.1)
|
||||
thor (1.2.1)
|
||||
thread_safe (0.3.6)
|
||||
tilt (2.0.10)
|
||||
tzinfo (1.2.6)
|
||||
tzinfo (1.2.9)
|
||||
thread_safe (~> 0.1)
|
||||
tzinfo-data (1.2019.3)
|
||||
tzinfo-data (1.2021.5)
|
||||
tzinfo (>= 1.0.0)
|
||||
uglifier (4.2.0)
|
||||
execjs (>= 0.3.0, < 3)
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
PermissionDialog,
|
||||
removeFromArray,
|
||||
} from '@standardnotes/snjs';
|
||||
import { PANEL_NAME_NOTES, PANEL_NAME_NAVIGATION } from '@/views/constants';
|
||||
import { PANEL_NAME_NOTES, PANEL_NAME_NAVIGATION } from '@/constants';
|
||||
import { STRING_DEFAULT_FILE_ERROR } from '@/strings';
|
||||
import { alertDialog } from '@/services/alertService';
|
||||
import { WebAppEvent, WebApplication } from '@/ui_models/application';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { WebApplication } from '@/ui_models/application';
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
import { MENU_MARGIN_FROM_APP_BORDER } from '@/views/constants';
|
||||
import { MENU_MARGIN_FROM_APP_BORDER } from '@/constants';
|
||||
import {
|
||||
Disclosure,
|
||||
DisclosureButton,
|
||||
@@ -101,7 +101,7 @@ export const ChangeEditorButton: FunctionComponent<Props> = observer(
|
||||
}}
|
||||
onBlur={closeOnBlur}
|
||||
ref={buttonRef}
|
||||
className="sn-icon-button"
|
||||
className="sn-icon-button border-contrast"
|
||||
>
|
||||
<VisuallyHidden>Change editor</VisuallyHidden>
|
||||
<Icon type="dashboard" className="block" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { SmartTagsSection } from '@/components/Tags/SmartTagsSection';
|
||||
import { TagsSection } from '@/components/Tags/TagsSection';
|
||||
import { WebApplication } from '@/ui_models/application';
|
||||
import { PANEL_NAME_NAVIGATION } from '@/views/constants';
|
||||
import { PANEL_NAME_NAVIGATION } from '@/constants';
|
||||
import { ApplicationEvent, PrefKey } from '@standardnotes/snjs';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { FunctionComponent } from 'preact';
|
||||
|
||||
@@ -9,7 +9,7 @@ import { NotesListItem } from './NotesListItem';
|
||||
import {
|
||||
FOCUSABLE_BUT_NOT_TABBABLE,
|
||||
NOTES_LIST_SCROLL_THRESHOLD,
|
||||
} from '@/views/constants';
|
||||
} from '@/constants';
|
||||
|
||||
type Props = {
|
||||
application: WebApplication;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { AppState } from '@/ui_models/app_state';
|
||||
import {
|
||||
MENU_MARGIN_FROM_APP_BORDER,
|
||||
MAX_MENU_SIZE_MULTIPLIER,
|
||||
} from '@/views/constants';
|
||||
} from '@/constants';
|
||||
import {
|
||||
Disclosure,
|
||||
DisclosureButton,
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
MENU_MARGIN_FROM_APP_BORDER,
|
||||
MAX_MENU_SIZE_MULTIPLIER,
|
||||
BYTES_IN_ONE_MEGABYTE,
|
||||
} from '@/views/constants';
|
||||
} from '@/constants';
|
||||
|
||||
export type NotesOptionsProps = {
|
||||
application: WebApplication;
|
||||
@@ -560,7 +560,7 @@ export const NotesOptions = observer(
|
||||
}}
|
||||
>
|
||||
<Icon type="trash" className={iconClass} />
|
||||
Move to Trash
|
||||
Move to trash
|
||||
</button>
|
||||
))}
|
||||
{trashed && (
|
||||
|
||||
@@ -163,6 +163,12 @@ export const ChangeEditorMenu: FunctionComponent<ChangeEditorMenuProps> = ({
|
||||
};
|
||||
|
||||
const selectEditor = async (itemToBeSelected: EditorMenuItem) => {
|
||||
const areBothEditorsPlain = !currentEditor && !itemToBeSelected.component;
|
||||
|
||||
if (areBothEditorsPlain) {
|
||||
return;
|
||||
}
|
||||
|
||||
let shouldSelectEditor = true;
|
||||
|
||||
if (itemToBeSelected.component) {
|
||||
|
||||
@@ -69,7 +69,7 @@ export const NotesOptionsPanel = observer(
|
||||
}}
|
||||
onBlur={closeOnBlur}
|
||||
ref={buttonRef}
|
||||
className="sn-icon-button"
|
||||
className="sn-icon-button border-contrast"
|
||||
>
|
||||
<VisuallyHidden>Actions</VisuallyHidden>
|
||||
<Icon type="more" className="block" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { KeyboardKey, KeyboardModifier } from '@/services/ioService';
|
||||
import { WebApplication } from '@/ui_models/application';
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
import { PANEL_NAME_NOTES } from '@/views/constants';
|
||||
import { PANEL_NAME_NOTES } from '@/constants';
|
||||
import { PrefKey } from '@standardnotes/snjs';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { FunctionComponent } from 'preact';
|
||||
|
||||
@@ -28,7 +28,9 @@ export const PinNoteButton: FunctionComponent<Props> = observer(
|
||||
|
||||
return (
|
||||
<button
|
||||
className={`sn-icon-button ${pinned ? 'toggled' : ''} ${className}`}
|
||||
className={`sn-icon-button border-contrast ${
|
||||
pinned ? 'toggled' : ''
|
||||
} ${className}`}
|
||||
onClick={togglePinned}
|
||||
>
|
||||
<VisuallyHidden>Pin selected notes</VisuallyHidden>
|
||||
|
||||
@@ -58,9 +58,9 @@ const toggleFocusMode = (enabled: boolean) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const sortThemes = (a: SNTheme, b: SNTheme) => {
|
||||
const aIsLayerable = a.isLayerable();
|
||||
const bIsLayerable = b.isLayerable();
|
||||
export const sortThemes = (a: ThemeItem, b: ThemeItem) => {
|
||||
const aIsLayerable = a.component?.isLayerable();
|
||||
const bIsLayerable = b.component?.isLayerable();
|
||||
|
||||
if (aIsLayerable && !bIsLayerable) {
|
||||
return 1;
|
||||
@@ -105,15 +105,13 @@ export const QuickSettingsMenu: FunctionComponent<MenuProps> = observer(
|
||||
const reloadThemes = useCallback(() => {
|
||||
const themes = (
|
||||
application.getDisplayableItems(ContentType.Theme) as SNTheme[]
|
||||
)
|
||||
.sort(sortThemes)
|
||||
.map((item) => {
|
||||
return {
|
||||
name: item.name,
|
||||
identifier: item.identifier,
|
||||
component: item,
|
||||
};
|
||||
}) as ThemeItem[];
|
||||
).map((item) => {
|
||||
return {
|
||||
name: item.name,
|
||||
identifier: item.identifier,
|
||||
component: item,
|
||||
};
|
||||
}) as ThemeItem[];
|
||||
|
||||
GetFeatures()
|
||||
.filter(
|
||||
@@ -132,7 +130,7 @@ export const QuickSettingsMenu: FunctionComponent<MenuProps> = observer(
|
||||
}
|
||||
});
|
||||
|
||||
setThemes(themes);
|
||||
setThemes(themes.sort(sortThemes));
|
||||
|
||||
setDefaultThemeOn(
|
||||
!themes
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { WebApplication } from '@/ui_models/application';
|
||||
import {
|
||||
Action,
|
||||
ActionVerb,
|
||||
HistoryEntry,
|
||||
NoteHistoryEntry,
|
||||
@@ -8,14 +9,13 @@ import {
|
||||
} from '@standardnotes/snjs';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { FunctionComponent } from 'preact';
|
||||
import { StateUpdater, useCallback, useMemo, useState } from 'preact/hooks';
|
||||
import { StateUpdater, useCallback, useState } from 'preact/hooks';
|
||||
import { useEffect } from 'react';
|
||||
import { LegacyHistoryList } from './LegacyHistoryList';
|
||||
import { RemoteHistoryList } from './RemoteHistoryList';
|
||||
import { SessionHistoryList } from './SessionHistoryList';
|
||||
import {
|
||||
LegacyHistoryEntry,
|
||||
ListGroup,
|
||||
RemoteRevisionListGroup,
|
||||
sortRevisionListIntoGroups,
|
||||
} from './utils';
|
||||
@@ -55,19 +55,45 @@ export const HistoryListContainer: FunctionComponent<Props> = observer(
|
||||
note
|
||||
) as NoteHistoryEntry[]
|
||||
);
|
||||
const [isFetchingLegacyHistory, setIsFetchingLegacyHistory] =
|
||||
useState(false);
|
||||
const [legacyHistory, setLegacyHistory] =
|
||||
useState<ListGroup<LegacyHistoryEntry>[]>();
|
||||
const legacyHistoryLength = useMemo(
|
||||
() => legacyHistory?.map((group) => group.entries).flat().length ?? 0,
|
||||
[legacyHistory]
|
||||
);
|
||||
const [legacyHistory, setLegacyHistory] = useState<Action[]>();
|
||||
|
||||
const [selectedTab, setSelectedTab] = useState<RevisionListTabType>(
|
||||
RevisionListTabType.Remote
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchLegacyHistory = async () => {
|
||||
const actionExtensions = application.actionsManager.getExtensions();
|
||||
actionExtensions.forEach(async (ext) => {
|
||||
const actionExtension =
|
||||
await application.actionsManager.loadExtensionInContextOfItem(
|
||||
ext,
|
||||
note
|
||||
);
|
||||
|
||||
if (!actionExtension) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isLegacyNoteHistoryExt = actionExtension?.actions.some(
|
||||
(action) => action.verb === ActionVerb.Nested
|
||||
);
|
||||
|
||||
if (!isLegacyNoteHistoryExt) {
|
||||
return;
|
||||
}
|
||||
|
||||
const legacyHistoryEntries = actionExtension.actions.filter(
|
||||
(action) => action.subactions?.[0]
|
||||
);
|
||||
|
||||
setLegacyHistory(legacyHistoryEntries);
|
||||
});
|
||||
};
|
||||
|
||||
fetchLegacyHistory();
|
||||
}, [application.actionsManager, note]);
|
||||
|
||||
const TabButton: FunctionComponent<{
|
||||
type: RevisionListTabType;
|
||||
}> = ({ type }) => {
|
||||
@@ -88,6 +114,43 @@ export const HistoryListContainer: FunctionComponent<Props> = observer(
|
||||
);
|
||||
};
|
||||
|
||||
const fetchAndSetLegacyRevision = useCallback(
|
||||
async (revisionListEntry: Action) => {
|
||||
setSelectedRemoteEntry(undefined);
|
||||
setSelectedRevision(undefined);
|
||||
setIsFetchingSelectedRevision(true);
|
||||
|
||||
try {
|
||||
if (!revisionListEntry.subactions?.[0]) {
|
||||
throw new Error('Could not find revision action url');
|
||||
}
|
||||
|
||||
const response = await application.actionsManager.runAction(
|
||||
revisionListEntry.subactions[0],
|
||||
note
|
||||
);
|
||||
|
||||
if (!response) {
|
||||
throw new Error('Could not fetch revision');
|
||||
}
|
||||
|
||||
setSelectedRevision(response.item as HistoryEntry);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
setSelectedRevision(undefined);
|
||||
} finally {
|
||||
setIsFetchingSelectedRevision(false);
|
||||
}
|
||||
},
|
||||
[
|
||||
application.actionsManager,
|
||||
note,
|
||||
setIsFetchingSelectedRevision,
|
||||
setSelectedRemoteEntry,
|
||||
setSelectedRevision,
|
||||
]
|
||||
);
|
||||
|
||||
const fetchAndSetRemoteRevision = useCallback(
|
||||
async (revisionListEntry: RevisionListEntry) => {
|
||||
setShowContentLockedScreen(false);
|
||||
@@ -132,12 +195,7 @@ export const HistoryListContainer: FunctionComponent<Props> = observer(
|
||||
<div className="flex border-0 border-b-1 border-solid border-main">
|
||||
<TabButton type={RevisionListTabType.Remote} />
|
||||
<TabButton type={RevisionListTabType.Session} />
|
||||
{isFetchingLegacyHistory && (
|
||||
<div className="flex items-center justify-center px-3 py-2.5">
|
||||
<div className="sk-spinner w-3 h-3 spinner-info" />
|
||||
</div>
|
||||
)}
|
||||
{legacyHistory && legacyHistoryLength > 0 && (
|
||||
{legacyHistory && legacyHistory.length > 0 && (
|
||||
<TabButton type={RevisionListTabType.Legacy} />
|
||||
)}
|
||||
</div>
|
||||
@@ -165,6 +223,7 @@ export const HistoryListContainer: FunctionComponent<Props> = observer(
|
||||
legacyHistory={legacyHistory}
|
||||
setSelectedRevision={setSelectedRevision}
|
||||
setSelectedRemoteEntry={setSelectedRemoteEntry}
|
||||
fetchAndSetLegacyRevision={fetchAndSetLegacyRevision}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/views/constants';
|
||||
import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/constants';
|
||||
import { FunctionComponent } from 'preact';
|
||||
|
||||
type HistoryListItemProps = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { HistoryEntry, RevisionListEntry } from '@standardnotes/snjs';
|
||||
import { Fragment, FunctionComponent } from 'preact';
|
||||
import { Action, HistoryEntry, RevisionListEntry } from '@standardnotes/snjs';
|
||||
import { FunctionComponent } from 'preact';
|
||||
import {
|
||||
StateUpdater,
|
||||
useCallback,
|
||||
@@ -11,19 +11,16 @@ import {
|
||||
import { useListKeyboardNavigation } from '../utils';
|
||||
import { RevisionListTabType } from './HistoryListContainer';
|
||||
import { HistoryListItem } from './HistoryListItem';
|
||||
import {
|
||||
LegacyHistoryEntry,
|
||||
ListGroup,
|
||||
previewHistoryEntryTitle,
|
||||
} from './utils';
|
||||
import { LegacyHistoryEntry } from './utils';
|
||||
|
||||
type Props = {
|
||||
selectedTab: RevisionListTabType;
|
||||
legacyHistory: ListGroup<LegacyHistoryEntry>[] | undefined;
|
||||
legacyHistory: Action[] | undefined;
|
||||
setSelectedRevision: StateUpdater<
|
||||
HistoryEntry | LegacyHistoryEntry | undefined
|
||||
>;
|
||||
setSelectedRemoteEntry: StateUpdater<RevisionListEntry | undefined>;
|
||||
fetchAndSetLegacyRevision: (revisionListEntry: Action) => Promise<void>;
|
||||
};
|
||||
|
||||
export const LegacyHistoryList: FunctionComponent<Props> = ({
|
||||
@@ -31,44 +28,36 @@ export const LegacyHistoryList: FunctionComponent<Props> = ({
|
||||
selectedTab,
|
||||
setSelectedRevision,
|
||||
setSelectedRemoteEntry,
|
||||
fetchAndSetLegacyRevision,
|
||||
}) => {
|
||||
const legacyHistoryListRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useListKeyboardNavigation(legacyHistoryListRef);
|
||||
|
||||
const legacyHistoryLength = useMemo(
|
||||
() => legacyHistory?.map((group) => group.entries).flat().length,
|
||||
[legacyHistory]
|
||||
);
|
||||
|
||||
const [selectedItemCreatedAt, setSelectedItemCreatedAt] = useState<Date>();
|
||||
const [selectedItemUrl, setSelectedItemUrl] = useState<string>();
|
||||
|
||||
const firstEntry = useMemo(() => {
|
||||
return legacyHistory?.find((group) => group.entries?.length)?.entries?.[0];
|
||||
return legacyHistory?.[0];
|
||||
}, [legacyHistory]);
|
||||
|
||||
const selectFirstEntry = useCallback(() => {
|
||||
if (firstEntry) {
|
||||
setSelectedItemCreatedAt(firstEntry.payload?.created_at);
|
||||
setSelectedRevision(firstEntry);
|
||||
setSelectedItemUrl(firstEntry.subactions?.[0].url);
|
||||
setSelectedRevision(undefined);
|
||||
fetchAndSetLegacyRevision(firstEntry);
|
||||
}
|
||||
}, [firstEntry, setSelectedRevision]);
|
||||
}, [fetchAndSetLegacyRevision, firstEntry, setSelectedRevision]);
|
||||
|
||||
useEffect(() => {
|
||||
if (firstEntry && !selectedItemCreatedAt) {
|
||||
if (firstEntry && !selectedItemUrl) {
|
||||
selectFirstEntry();
|
||||
} else if (!firstEntry) {
|
||||
setSelectedRevision(undefined);
|
||||
}
|
||||
}, [
|
||||
firstEntry,
|
||||
selectFirstEntry,
|
||||
selectedItemCreatedAt,
|
||||
setSelectedRevision,
|
||||
]);
|
||||
}, [firstEntry, selectFirstEntry, selectedItemUrl, setSelectedRevision]);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedTab === RevisionListTabType.Session) {
|
||||
if (selectedTab === RevisionListTabType.Legacy) {
|
||||
selectFirstEntry();
|
||||
legacyHistoryListRef.current?.focus();
|
||||
}
|
||||
@@ -77,33 +66,28 @@ export const LegacyHistoryList: FunctionComponent<Props> = ({
|
||||
return (
|
||||
<div
|
||||
className={`flex flex-col w-full h-full focus:shadow-none ${
|
||||
!legacyHistoryLength ? 'items-center justify-center' : ''
|
||||
!legacyHistory?.length ? 'items-center justify-center' : ''
|
||||
}`}
|
||||
ref={legacyHistoryListRef}
|
||||
>
|
||||
{legacyHistory?.map((group) =>
|
||||
group.entries && group.entries.length ? (
|
||||
<Fragment key={group.title}>
|
||||
<div className="px-3 mt-2.5 mb-1 font-semibold color-text uppercase color-grey-0 select-none">
|
||||
{group.title}
|
||||
</div>
|
||||
{group.entries.map((entry, index) => (
|
||||
<HistoryListItem
|
||||
key={index}
|
||||
isSelected={selectedItemCreatedAt === entry.payload.created_at}
|
||||
onClick={() => {
|
||||
setSelectedItemCreatedAt(entry.payload.created_at);
|
||||
setSelectedRevision(entry);
|
||||
setSelectedRemoteEntry(undefined);
|
||||
}}
|
||||
>
|
||||
{previewHistoryEntryTitle(entry)}
|
||||
</HistoryListItem>
|
||||
))}
|
||||
</Fragment>
|
||||
) : null
|
||||
)}
|
||||
{!legacyHistoryLength && (
|
||||
{legacyHistory?.map((entry) => {
|
||||
const url = entry.subactions?.[0].url;
|
||||
|
||||
return (
|
||||
<HistoryListItem
|
||||
key={url}
|
||||
isSelected={selectedItemUrl === url}
|
||||
onClick={() => {
|
||||
setSelectedItemUrl(url);
|
||||
setSelectedRemoteEntry(undefined);
|
||||
fetchAndSetLegacyRevision(entry);
|
||||
}}
|
||||
>
|
||||
{entry.label}
|
||||
</HistoryListItem>
|
||||
);
|
||||
})}
|
||||
{!legacyHistory?.length && (
|
||||
<div className="color-grey-0 select-none">No legacy history found</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -66,7 +66,7 @@ export const SelectedRevisionContent: FunctionComponent<SelectedRevisionContentP
|
||||
{!componentViewer && (
|
||||
<div className="relative flex-grow min-h-0 overflow-x-hidden overflow-y-auto">
|
||||
{selectedRevision.payload.content.text.length ? (
|
||||
<p className="p-4 pt-0">
|
||||
<p className="p-4 pt-0 color-text text-editor font-editor">
|
||||
{selectedRevision.payload.content.text}
|
||||
</p>
|
||||
) : (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DAYS_IN_A_WEEK, DAYS_IN_A_YEAR } from '@/views/constants';
|
||||
import { DAYS_IN_A_WEEK, DAYS_IN_A_YEAR } from '@/constants';
|
||||
import {
|
||||
HistoryEntry,
|
||||
NoteHistoryEntry,
|
||||
@@ -84,13 +84,17 @@ export const sortRevisionListIntoGroups = <EntryType extends RevisionEntry>(
|
||||
},
|
||||
];
|
||||
|
||||
const addBeforeLastGroup = (group: ListGroup<EntryType>) => {
|
||||
sortedGroups.splice(sortedGroups.length - 1, 0, group);
|
||||
};
|
||||
|
||||
revisionList?.forEach((entry) => {
|
||||
const groupIndex = getGroupIndexForEntry(entry, sortedGroups);
|
||||
|
||||
if (groupIndex > -1) {
|
||||
sortedGroups[groupIndex]?.entries?.push(entry);
|
||||
} else {
|
||||
sortedGroups.push({
|
||||
addBeforeLastGroup({
|
||||
title: formatDateAsMonthYearString(
|
||||
new Date(
|
||||
(entry as RevisionListEntry).created_at ??
|
||||
|
||||
@@ -4,7 +4,7 @@ import { JSXInternal } from 'preact/src/jsx';
|
||||
import { Icon } from '../Icon';
|
||||
import { Switch, SwitchProps } from '../Switch';
|
||||
import { IconType } from '@standardnotes/snjs';
|
||||
import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/views/constants';
|
||||
import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/constants';
|
||||
|
||||
export enum MenuItemType {
|
||||
IconButton,
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { KeyboardKey } from '@/services/ioService';
|
||||
import {
|
||||
FOCUSABLE_BUT_NOT_TABBABLE,
|
||||
MILLISECONDS_IN_A_DAY,
|
||||
} from '@/views/constants';
|
||||
import { FOCUSABLE_BUT_NOT_TABBABLE, MILLISECONDS_IN_A_DAY } from '@/constants';
|
||||
import {
|
||||
StateUpdater,
|
||||
useCallback,
|
||||
|
||||
@@ -23,7 +23,6 @@ module.exports = {
|
||||
self: {}, // fixes error happening on `import { SKAlert } from 'sn-stylekit'`
|
||||
},
|
||||
transform: {
|
||||
'\\.(pug)$': '../../../node_modules/jest-transform-pug',
|
||||
'^.+\\.(ts|tsx)?$': 'ts-jest',
|
||||
'\\.svg$': 'svg-jest',
|
||||
},
|
||||
|
||||
@@ -100,20 +100,6 @@ export class ThemeManager extends ApplicationService {
|
||||
this.setThemeAsPerColorScheme(prefersDarkColorScheme.matches);
|
||||
break;
|
||||
}
|
||||
case ApplicationEvent.LocalDataLoaded: {
|
||||
const themes = this.application.getDisplayableItems(
|
||||
ContentType.Theme
|
||||
) as SNTheme[];
|
||||
themes.forEach((theme) => {
|
||||
if (
|
||||
theme.active &&
|
||||
this.application.getFeatureStatus(theme.identifier) !==
|
||||
FeatureStatus.Entitled
|
||||
) {
|
||||
this.application.toggleTheme(theme);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,13 +123,19 @@ export class ThemeManager extends ApplicationService {
|
||||
let hasChange = false;
|
||||
for (const themeUuid of this.activeThemes) {
|
||||
const theme = this.application.findItem(themeUuid) as SNTheme;
|
||||
if (
|
||||
!theme ||
|
||||
this.application.getFeatureStatus(theme.identifier) !==
|
||||
FeatureStatus.Entitled
|
||||
) {
|
||||
if (!theme) {
|
||||
this.deactivateTheme(themeUuid);
|
||||
hasChange = true;
|
||||
} else {
|
||||
const status = this.application.getFeatureStatus(theme.identifier);
|
||||
if (status !== FeatureStatus.Entitled) {
|
||||
if (theme.active) {
|
||||
this.application.toggleTheme(theme);
|
||||
} else {
|
||||
this.deactivateTheme(theme.uuid);
|
||||
}
|
||||
hasChange = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +152,7 @@ export class ThemeManager extends ApplicationService {
|
||||
private async activateCachedThemes() {
|
||||
const cachedThemes = await this.getCachedThemes();
|
||||
for (const theme of cachedThemes) {
|
||||
this.activateTheme(theme);
|
||||
this.activateTheme(theme, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,22 +194,26 @@ export class ThemeManager extends ApplicationService {
|
||||
}
|
||||
}
|
||||
|
||||
private activateTheme(theme: SNTheme) {
|
||||
private activateTheme(theme: SNTheme, skipEntitlementCheck = false) {
|
||||
if (this.activeThemes.find((uuid) => uuid === theme.uuid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!skipEntitlementCheck &&
|
||||
this.application.getFeatureStatus(theme.identifier) !==
|
||||
FeatureStatus.Entitled
|
||||
FeatureStatus.Entitled
|
||||
) {
|
||||
return;
|
||||
}
|
||||
this.activeThemes.push(theme.uuid);
|
||||
|
||||
const url = this.application.componentManager.urlForComponent(theme);
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.activeThemes.push(theme.uuid);
|
||||
|
||||
const link = document.createElement('link');
|
||||
link.href = url;
|
||||
link.type = 'text/css';
|
||||
|
||||
5
app/assets/javascripts/typings/pug.d.ts
vendored
5
app/assets/javascripts/typings/pug.d.ts
vendored
@@ -1,5 +0,0 @@
|
||||
declare module "*.pug" {
|
||||
import { compileTemplate } from 'pug';
|
||||
const content: compileTemplate;
|
||||
export default content;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { confirmDialog } from '@/services/alertService';
|
||||
import { KeyboardModifier } from '@/services/ioService';
|
||||
import { StringEmptyTrash, Strings, StringUtils } from '@/strings';
|
||||
import { MENU_MARGIN_FROM_APP_BORDER } from '@/views/constants';
|
||||
import { MENU_MARGIN_FROM_APP_BORDER } from '@/constants';
|
||||
import {
|
||||
UuidString,
|
||||
SNNote,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Platform, platformFromString } from '@standardnotes/snjs';
|
||||
import { IsDesktopPlatform, IsWebPlatform } from '@/version';
|
||||
import { EMAIL_REGEX } from '@Views/constants';
|
||||
import { EMAIL_REGEX } from '../constants';
|
||||
export { isMobile } from './isMobile';
|
||||
|
||||
declare const process: {
|
||||
|
||||
@@ -946,3 +946,11 @@
|
||||
.sn-component .border-t-0 {
|
||||
border-top-width: 0;
|
||||
}
|
||||
|
||||
.text-editor {
|
||||
font-size: var(--sn-stylekit-font-size-editor);
|
||||
}
|
||||
|
||||
.sn-component .border-contrast {
|
||||
border-color: var(--sn-stylekit-contrast-border-color);
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
<link color="#5bbad5" href="favicon/safari-pinned-tab.svg" rel="mask-icon"></link>
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<meta ng-bind="title" content="Standard Notes" name="apple-mobile-web-app-title"/>
|
||||
<meta ng-bind="title" content="Standard Notes" name="application-name"/>
|
||||
<meta content="Standard Notes" name="apple-mobile-web-app-title"/>
|
||||
<meta content="Standard Notes" name="application-name"/>
|
||||
<base href="/"></base>
|
||||
|
||||
<title>Notes · Standard Notes</title>
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
</link>
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<meta ng-bind="title" content="Standard Notes" name="apple-mobile-web-app-title" />
|
||||
<meta ng-bind="title" content="Standard Notes" name="application-name" />
|
||||
<meta content="Standard Notes" name="apple-mobile-web-app-title" />
|
||||
<meta content="Standard Notes" name="application-name" />
|
||||
|
||||
<title>Dev · Notes · Standard Notes</title>
|
||||
</head>
|
||||
|
||||
88
package.json
88
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "standard-notes-web",
|
||||
"version": "3.11.0",
|
||||
"version": "3.11.1",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -21,79 +21,73 @@
|
||||
"prepare": "husky install"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.15.8",
|
||||
"@babel/plugin-transform-react-jsx": "^7.14.9",
|
||||
"@babel/preset-env": "^7.15.8",
|
||||
"@babel/preset-typescript": "^7.15.0",
|
||||
"@babel/core": "^7.17.5",
|
||||
"@babel/plugin-transform-react-jsx": "^7.17.3",
|
||||
"@babel/preset-env": "^7.16.11",
|
||||
"@babel/preset-typescript": "^7.16.7",
|
||||
"@reach/disclosure": "^0.16.2",
|
||||
"@reach/visually-hidden": "^0.16.0",
|
||||
"@svgr/webpack": "^6.2.1",
|
||||
"@types/jest": "^27.0.3",
|
||||
"@types/lodash": "^4.14.176",
|
||||
"@types/pug": "^2.0.5",
|
||||
"@types/react": "^17.0.31",
|
||||
"@typescript-eslint/eslint-plugin": "^5.1.0",
|
||||
"@typescript-eslint/parser": "^5.1.0",
|
||||
"@types/jest": "^27.4.0",
|
||||
"@types/lodash": "^4.14.178",
|
||||
"@types/react": "^17.0.39",
|
||||
"@typescript-eslint/eslint-plugin": "^5.12.0",
|
||||
"@typescript-eslint/parser": "^5.12.0",
|
||||
"apply-loader": "^2.0.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^8.2.3",
|
||||
"connect": "^3.7.0",
|
||||
"copy-webpack-plugin": "^10.2.0",
|
||||
"css-loader": "^6.4.0",
|
||||
"dotenv": "^10.0.0",
|
||||
"eslint": "^8.0.1",
|
||||
"copy-webpack-plugin": "^10.2.4",
|
||||
"css-loader": "^6.6.0",
|
||||
"dotenv": "^16.0.0",
|
||||
"eslint": "^8.9.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-react": "^7.26.1",
|
||||
"eslint-plugin-react-hooks": "^4.2.1-beta-149b420f6-20211119",
|
||||
"eslint-plugin-react": "^7.28.0",
|
||||
"eslint-plugin-react-hooks": "^4.3.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-webpack-plugin": "^5.4.0",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"husky": "^7.0.4",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"jest": "^27.3.1",
|
||||
"jest-transform-pug": "^0.1.0",
|
||||
"lint-staged": ">=10",
|
||||
"jest": "^27.5.1",
|
||||
"lint-staged": ">=12",
|
||||
"lodash": "^4.17.21",
|
||||
"mini-css-extract-plugin": "^2.4.3",
|
||||
"ng-cache-loader": "0.0.26",
|
||||
"node-sass": "^6.0.1",
|
||||
"prettier": "^2.5.0",
|
||||
"pretty-quick": "^3.1.2",
|
||||
"pug": "^3.0.2",
|
||||
"pug-jest": "^1.0.1",
|
||||
"pug-loader": "^2.4.0",
|
||||
"sass-loader": "^12.2.0",
|
||||
"serve-static": "^1.14.1",
|
||||
"@standardnotes/stylekit": "5.7.0",
|
||||
"mini-css-extract-plugin": "^2.5.3",
|
||||
"node-sass": "^7.0.1",
|
||||
"prettier": "^2.5.1",
|
||||
"pretty-quick": "^3.1.3",
|
||||
"sass-loader": "^12.6.0",
|
||||
"serve-static": "^1.14.2",
|
||||
"@standardnotes/stylekit": "5.8.0",
|
||||
"svg-jest": "^1.0.1",
|
||||
"ts-jest": "^27.0.7",
|
||||
"ts-jest": "^27.1.3",
|
||||
"ts-loader": "^9.2.6",
|
||||
"typescript": "4.4.4",
|
||||
"typescript": "4.5.5",
|
||||
"typescript-eslint": "0.0.1-alpha.0",
|
||||
"webpack": "^5.59.1",
|
||||
"webpack-cli": "^4.9.1",
|
||||
"webpack-dev-server": "^4.3.1",
|
||||
"webpack": "^5.69.1",
|
||||
"webpack-cli": "^4.9.2",
|
||||
"webpack-dev-server": "^4.7.4",
|
||||
"webpack-merge": "^5.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@bugsnag/js": "^7.13.2",
|
||||
"@bugsnag/js": "^7.16.1",
|
||||
"@reach/alert": "^0.16.0",
|
||||
"@reach/alert-dialog": "^0.16.2",
|
||||
"@reach/checkbox": "^0.16.0",
|
||||
"@reach/dialog": "^0.16.2",
|
||||
"@reach/listbox": "^0.16.2",
|
||||
"@reach/tooltip": "^0.16.2",
|
||||
"@standardnotes/components": "1.7.3",
|
||||
"@standardnotes/features": "1.32.6",
|
||||
"@standardnotes/snjs": "2.61.0",
|
||||
"@standardnotes/components": "1.7.4",
|
||||
"@standardnotes/features": "1.32.8",
|
||||
"@standardnotes/snjs": "2.61.4",
|
||||
"@standardnotes/settings": "^1.11.3",
|
||||
"@standardnotes/sncrypto-web": "1.7.0",
|
||||
"mobx": "^6.3.5",
|
||||
"mobx-react-lite": "^3.2.2",
|
||||
"preact": "^10.5.15",
|
||||
"mobx": "^6.4.0",
|
||||
"mobx-react-lite": "^3.3.0",
|
||||
"preact": "^10.6.6",
|
||||
"qrcode.react": "^1.0.1",
|
||||
"react-dnd": "^14.0.4",
|
||||
"react-dnd-html5-backend": "^14.0.2",
|
||||
"react-dnd-touch-backend": "^14.1.1"
|
||||
"react-dnd": "^15.1.1",
|
||||
"react-dnd-html5-backend": "^15.1.2",
|
||||
"react-dnd-touch-backend": "^15.1.1"
|
||||
},
|
||||
"lint-staged": {
|
||||
"app/**/*.{js,ts,jsx,tsx}": "eslint --cache --fix",
|
||||
|
||||
@@ -40,9 +40,9 @@
|
||||
"binary": "4e08fb2de17ab480787a1e042b2d43106e2798093e760fc507ed773401d27c71"
|
||||
},
|
||||
"org.standardnotes.bold-editor": {
|
||||
"version": "1.3.3",
|
||||
"base64": "51a5d2e77aacbcfda21b4a3429e9fe3fb6b61175e5188b6ec26854432ac41fc2",
|
||||
"binary": "a30533208fbc33f115786ff912b6d605052adda03a62b47513ce390931fe11d1"
|
||||
"version": "1.3.5",
|
||||
"base64": "bcecfd1a6ee1909c9f484890cf58d6d52479f8d33c16e1d5d916d1a78a75b90f",
|
||||
"binary": "84d6ca88665d4d6a1aeb456f8acce1a662bfe4550128aac1fb748abed974f236"
|
||||
},
|
||||
"org.standardnotes.plus-editor": {
|
||||
"version": "1.6.1",
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "sn-bold-editor",
|
||||
"version": "1.3.3",
|
||||
"version": "1.3.5",
|
||||
"main": "dist/dist.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
@@ -25,8 +25,8 @@
|
||||
"dompurify": "^2.2.9",
|
||||
"eslint": "^7.23.0",
|
||||
"eslint-plugin-react": "^7.23.1",
|
||||
"filesafe-embed": "1.0.11",
|
||||
"filesafe-js": "1.0.4",
|
||||
"filesafe-embed": "1.0.13",
|
||||
"filesafe-js": "1.0.5",
|
||||
"html-webpack-plugin": "^5.3.1",
|
||||
"mini-css-extract-plugin": "^1.4.0",
|
||||
"node-sass": "^5.0.0",
|
||||
|
||||
@@ -76,29 +76,6 @@ module.exports = (env) => {
|
||||
test: /\.svg$/i,
|
||||
use: ['@svgr/webpack'],
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
exclude: [path.resolve(__dirname, 'index.html')],
|
||||
use: [
|
||||
{
|
||||
loader: 'ng-cache-loader',
|
||||
options: {
|
||||
prefix: 'templates:**',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.pug$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'apply-loader',
|
||||
},
|
||||
{
|
||||
loader: 'pug-loader',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user