diff --git a/CHANGELOG.md b/CHANGELOG.md index d024be730..195ac77c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,9 +32,9 @@ - Highlighted code blocks can now use line wrapping and line numbers at once - Images, videos, and other non-text content is now wider in View Mode - Notes may now be deleted directly from the history page -- HedgeDoc instances can now be branded either with a '@ ' or '@ ' after the HedgeDoc logo and text +- HedgeDoc instances can be branded either with a '@ \' or '@ \' after the HedgeDoc logo and text - Images will be loaded via proxy if an image proxy is configured in the backend -- Asciinema videos may now be embedded by pasting the URL of one video into a single line +- Asciinema videos may be embedded by pasting the URL of one video into a single line - The toolbar includes an emoji and fork-awesome icon picker. - Collapsable blocks can be added via a toolbar button or via autocompletion of " (add image) and (add link) toolbar buttons, put selected links directly in the `()` instead of the `[]` part of the generated markdown +- The (add image) and (add link) toolbar buttons put selected links directly in the `()` instead of the `[]` part of the generated markdown. - The help dialog has multiple tabs, and is a bit more organized. - Use KaTeX instead of MathJax. ([Why?](https://community.codimd.org/t/frequently-asked-questions/190)) -- The access tokens for the CLI and 3rd-party-clients can be managed in the user profile. +- The dark-mode is also applied to the read-only-view and can be toggled from there. +- Access tokens for the CLI and 3rd-party-clients can be managed in the user profile. --- diff --git a/public/api/v2/notes/banner b/public/api/v2/notes/banner index 9ec51b790..3642978c1 100644 --- a/public/api/v2/notes/banner +++ b/public/api/v2/notes/banner @@ -2,12 +2,11 @@ "id": "ABC123", "alias": "banner", "lastChange": { - "userId": "snskxnksnxksnxksnx", - "username": "testy", - "timestamp": 123456789 + "userId": "test", + "timestamp": 1600033920 }, "viewcount": 0, - "createtime": "2020-05-22T20:46:08.962Z", + "createtime": 1600033920, "content": "This is the test banner text", "authorship": [], "preVersionTwoNote": true diff --git a/public/api/v2/notes/old b/public/api/v2/notes/old index 07e07dc88..c4b194892 100644 --- a/public/api/v2/notes/old +++ b/public/api/v2/notes/old @@ -2,12 +2,11 @@ "id": "ABC123", "alias": "old", "lastChange": { - "userId": "snskxnksnxksnxksnx", - "username": "testy", - "timestamp": 123456789 + "userId": "test", + "timestamp": 1600033920 }, "viewcount": 0, - "createtime": "2020-05-22T20:46:08.962Z", + "createtime": 1600033920, "content": "test123", "authorship": [], "preVersionTwoNote": false diff --git a/public/locales/en.json b/public/locales/en.json index 3dac48fda..9c9fa1170 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -393,6 +393,18 @@ "clickToLoad": "Click to load" } }, + "views": { + "presentation": {}, + "readOnly": { + "viewCount": "views", + "editNote": "Edit this note", + "loading": "Loading note contents ...", + "error": { + "title": "Error while loading note", + "description": "Probably the requested note does not exist or was deleted." + } + } + }, "common": { "import": "Import", "export": "Export", diff --git a/src/api/notes/index.ts b/src/api/notes/index.ts index d96e1f8e8..adeb77634 100644 --- a/src/api/notes/index.ts +++ b/src/api/notes/index.ts @@ -2,7 +2,6 @@ import { defaultFetchConfig, expectResponseCode, getApiUrl } from '../utils' interface LastChange { userId: string - username: string timestamp: number } @@ -11,14 +10,16 @@ export interface Note { alias: string lastChange: LastChange viewcount: number - createtime: string + createtime: number content: string authorship: number[] preVersionTwoNote: boolean } export const getNote = async (noteId: string): Promise => { - const response = await fetch(getApiUrl() + `/notes/${noteId}`) + const response = await fetch(getApiUrl() + `/notes/${noteId}`, { + ...defaultFetchConfig + }) expectResponseCode(response) return await response.json() as Promise } diff --git a/src/components/common/document-title/note-title-extractor.ts b/src/components/common/document-title/note-title-extractor.ts new file mode 100644 index 000000000..ca1346b36 --- /dev/null +++ b/src/components/common/document-title/note-title-extractor.ts @@ -0,0 +1,11 @@ +import { YAMLMetaData } from '../../editor/yaml-metadata/yaml-metadata' + +export const extractNoteTitle = (defaultTitle: string, noteMetadata?: YAMLMetaData, firstHeading?: string): string => { + if (noteMetadata?.title && noteMetadata?.title !== '') { + return noteMetadata.title + } else if (noteMetadata?.opengraph && noteMetadata?.opengraph.get('title') && noteMetadata?.opengraph.get('title') !== '') { + return (noteMetadata?.opengraph.get('title') ?? defaultTitle) + } else { + return (firstHeading ?? defaultTitle).trim() + } +} diff --git a/src/components/common/links/external-link.tsx b/src/components/common/links/external-link.tsx index 8736a790c..6c1021e53 100644 --- a/src/components/common/links/external-link.tsx +++ b/src/components/common/links/external-link.tsx @@ -4,13 +4,14 @@ import { IconName } from '../fork-awesome/types' import { ShowIf } from '../show-if/show-if' import { LinkWithTextProps } from './types' -export const ExternalLink: React.FC = ({ href, text, icon, id, className = 'text-light' }) => { +export const ExternalLink: React.FC = ({ href, text, icon, id, className = 'text-light', title }) => { return ( diff --git a/src/components/common/links/internal-link.tsx b/src/components/common/links/internal-link.tsx index 7fc1a4f95..34def4159 100644 --- a/src/components/common/links/internal-link.tsx +++ b/src/components/common/links/internal-link.tsx @@ -5,11 +5,12 @@ import { IconName } from '../fork-awesome/types' import { ShowIf } from '../show-if/show-if' import { LinkWithTextProps } from './types' -export const InternalLink: React.FC = ({ href, text, icon, id, className = 'text-light' }) => { +export const InternalLink: React.FC = ({ href, text, icon, id, className = 'text-light', title }) => { return (   diff --git a/src/components/common/links/types.d.ts b/src/components/common/links/types.d.ts index f6298252d..b9d6ad168 100644 --- a/src/components/common/links/types.d.ts +++ b/src/components/common/links/types.d.ts @@ -6,6 +6,7 @@ interface GeneralLinkProp { icon?: IconName id?: string className?: string + title?: string } export interface LinkWithTextProps extends GeneralLinkProp { diff --git a/src/components/common/user-avatar/user-avatar.scss b/src/components/common/user-avatar/user-avatar.scss index 8f15e9959..a1c9dd4f0 100644 --- a/src/components/common/user-avatar/user-avatar.scss +++ b/src/components/common/user-avatar/user-avatar.scss @@ -1,8 +1,15 @@ .user-avatar { width: 20px; height: 20px; -} -.user-name { - font-size: 1rem; + &.lg { + width: 30px; + height: 30px; + } + + &.sm { + width: 16px; + height: 16px; + } + } diff --git a/src/components/common/user-avatar/user-avatar.tsx b/src/components/common/user-avatar/user-avatar.tsx index 64b4f73ce..e5e808972 100644 --- a/src/components/common/user-avatar/user-avatar.tsx +++ b/src/components/common/user-avatar/user-avatar.tsx @@ -4,25 +4,26 @@ import { ShowIf } from '../show-if/show-if' import './user-avatar.scss' export interface UserAvatarProps { - name: string; - photo: string; - additionalClasses?: string; - showName?: boolean + size?: 'sm' | 'lg' + name: string; + photo: string; + additionalClasses?: string; + showName?: boolean } -const UserAvatar: React.FC = ({ name, photo, additionalClasses = '', showName = true }) => { +const UserAvatar: React.FC = ({ name, photo, size, additionalClasses = '', showName = true }) => { const { t } = useTranslation() return ( {t('common.avatarOf', - {name} + {name} ) diff --git a/src/components/editor/app-bar/app-bar.tsx b/src/components/editor/app-bar/app-bar.tsx index 3c380ded9..90781e149 100644 --- a/src/components/editor/app-bar/app-bar.tsx +++ b/src/components/editor/app-bar/app-bar.tsx @@ -16,7 +16,16 @@ import { HelpButton } from './help-button/help-button' import { NavbarBranding } from './navbar-branding' import { SyncScrollButtons } from './sync-scroll-buttons/sync-scroll-buttons' -export const AppBar: React.FC = () => { +export enum AppBarMode { + BASIC, + EDITOR +} + +export interface AppBarProps { + mode: AppBarMode +} + +export const AppBar: React.FC = ({ mode }) => { const { t } = useTranslation() const { id } = useParams() const userExists = useSelector((state: ApplicationState) => !!state.user) @@ -25,15 +34,19 @@ export const AppBar: React.FC = () => {