Skip to content

Commit

Permalink
perf(app): add media note index
Browse files Browse the repository at this point in the history
  • Loading branch information
aidenlx committed Jan 17, 2024
1 parent f0db521 commit 5d6ae4f
Show file tree
Hide file tree
Showing 14 changed files with 435 additions and 343 deletions.
1 change: 1 addition & 0 deletions apps/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"@radix-ui/react-tooltip": "^1.0.6",
"@vidstack/react": "npm:@aidenlx/[email protected]",
"ahooks": "^3.7.8",
"assert-never": "^1.2.1",
"clsx": "^1.2.1",
"dayjs": "^1.11.10",
"iso-639-1": "^3.1.0",
Expand Down
19 changes: 10 additions & 9 deletions apps/app/src/media-note/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { TFile } from "obsidian";
import { TFile } from "obsidian";
import type { AudioFileView, VideoFileView } from "@/media-view/file-view";
import { isMediaFileViewType } from "@/media-view/file-view";
import type { MediaEmbedView } from "@/media-view/iframe-view";
Expand All @@ -8,22 +8,23 @@ import { isMediaUrlViewType } from "@/media-view/url-view";
import type { MediaWebpageView } from "@/media-view/webpage-view";
import { MEDIA_WEBPAGE_VIEW_TYPE } from "@/media-view/webpage-view";
import type MxPlugin from "@/mx-main";
import { parseUrl } from "./manager/url-info";
import { takeTimestampOnFile, takeTimestampOnUrl } from "./timestamp";
import { noteUtils } from "./utils";
import { openMedia } from "./utils";

export function handleMediaNote(this: MxPlugin) {
const { openMedia, getMediaInfo } = noteUtils(this.app);
const { workspace } = this.app;
this.registerEvent(
this.app.workspace.on("file-menu", (menu, file, _source, _leaf) => {
const mediaInfo = getMediaInfo(file);
if (!(file instanceof TFile)) return;
const mediaInfo = this.mediaNote.findMedia(file);
if (!mediaInfo) return;
menu.addItem((item) =>
item
.setSection("view")
.setIcon("play")
.setTitle("Open linked media")
.onClick(() => openMedia(mediaInfo, file as TFile)),
.onClick(() => openMedia(mediaInfo, this.app)),
);
}),
);
Expand All @@ -39,9 +40,9 @@ export function handleMediaNote(this: MxPlugin) {
const viewType = view.getViewType();
if (isMediaFileViewType(viewType)) {
if (checking) return true;
const takeTimestamp = takeTimestampOnFile(
view as VideoFileView | AudioFileView,
(player) => player.file,
const fileView = view as VideoFileView | AudioFileView;
const takeTimestamp = takeTimestampOnFile(fileView, () =>
fileView.getMediaInfo(),
);
takeTimestamp();
} else if (
Expand All @@ -56,7 +57,7 @@ export function handleMediaNote(this: MxPlugin) {
| AudioUrlView
| MediaWebpageView
| MediaEmbedView,
(player) => player.source,
(player) => parseUrl(player.source),
);
takeTimestamp();
}
Expand Down
81 changes: 4 additions & 77 deletions apps/app/src/media-note/link-click/external.ts
Original file line number Diff line number Diff line change
@@ -1,84 +1,11 @@
import type { WorkspaceLeaf } from "obsidian";
import { noHash } from "@/lib/url";
import { MEDIA_EMBED_VIEW_TYPE } from "@/media-view/iframe-view";
import type {
MediaEmbedViewType,
MediaEmbedViewState,
} from "@/media-view/iframe-view";
import type { MediaUrlViewType } from "@/media-view/url-view";
import { MEDIA_URL_VIEW_TYPE } from "@/media-view/url-view";
import { MEDIA_WEBPAGE_VIEW_TYPE } from "@/media-view/webpage-view";
import type {
MediaWebpageViewType,
MediaWebpageViewState,
} from "@/media-view/webpage-view";
import type { MediaEmbedViewState } from "@/media-view/iframe-view";
import type { MediaWebpageViewState } from "@/media-view/webpage-view";
import type MxPlugin from "@/mx-main";
import { matchHostForEmbed } from "@/web/match-embed";
import { matchHostForUrl } from "@/web/match-url";
import { matchHostForWeb, SupportedWebHost } from "@/web/match-webpage";
import type { UrlMediaInfo } from "../manager/url-info";
import { parseUrl } from "../manager/url-info";
import { openInOpenedPlayer } from "./opened";

export interface UrlMediaInfo {
viewType: MediaUrlViewType | MediaEmbedViewType | MediaWebpageViewType;
source: URL;
original: string;
hash: string;
isSameSource: (src: string) => boolean;
}
export function parseUrl(url: string): UrlMediaInfo | null {
const directlinkInfo = matchHostForUrl(url);

if (directlinkInfo) {
return {
viewType: MEDIA_URL_VIEW_TYPE[directlinkInfo.type],
source: directlinkInfo.source,
original: url,
hash: directlinkInfo.source.hash,
isSameSource: (src) => {
const matched = matchHostForUrl(src);
return (
!!matched &&
noHash(matched.cleanUrl) === noHash(directlinkInfo.cleanUrl)
);
},
};
}

const embedInfo = matchHostForEmbed(url);

if (embedInfo) {
return {
viewType: MEDIA_EMBED_VIEW_TYPE,
source: embedInfo.source,
original: url,
hash: embedInfo.source.hash,
isSameSource: (src) => {
const matched = matchHostForEmbed(src);
return (
!!matched && noHash(matched.cleanUrl) === noHash(embedInfo.cleanUrl)
);
},
};
}

const webpageInfo = matchHostForWeb(url);
if (webpageInfo && webpageInfo.type !== SupportedWebHost.Generic) {
return {
viewType: MEDIA_WEBPAGE_VIEW_TYPE,
source: webpageInfo.source,
original: url,
hash: webpageInfo.source.hash,
isSameSource: (src) => {
const matched = matchHostForWeb(src);
return (
!!matched && noHash(matched.cleanUrl) === noHash(webpageInfo.cleanUrl)
);
},
};
}
return null;
}

export async function onExternalLinkClick(
this: MxPlugin,
url: string,
Expand Down
35 changes: 8 additions & 27 deletions apps/app/src/media-note/link-click/internal.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,9 @@
import type { TFile } from "obsidian";
import { parseLinktext } from "obsidian";
import {
MEDIA_FILE_VIEW_TYPE,
isMediaFileViewType,
type MediaFileViewType,
} from "@/media-view/file-view";
import { MEDIA_FILE_VIEW_TYPE } from "@/media-view/file-view";
import type MxPlugin from "@/mx-main";
import { checkMediaType } from "@/patch/utils";
import { openInOpenedPlayer } from "./opened";

export interface FileMediaInfo {
viewType: MediaFileViewType;
file: TFile;
hash: string;
}

export function isFileMediaInfo(info: unknown): info is FileMediaInfo {
return isMediaFileViewType((info as FileMediaInfo).viewType);
}

export function onInternalLinkClick(
this: MxPlugin,
linktext: string,
Expand All @@ -34,17 +19,13 @@ export function onInternalLinkClick(
fallback();
return;
}
if (
!newLeaf &&
openInOpenedPlayer(
{
file: linkFile,
hash: subpath,
viewType: MEDIA_FILE_VIEW_TYPE[mediaType],
},
workspace,
)
) {
const mediaInfo = {
file: linkFile,
hash: subpath,
type: mediaType,
viewType: MEDIA_FILE_VIEW_TYPE[mediaType],
};
if (!newLeaf && openInOpenedPlayer(mediaInfo, workspace)) {
return;
}
fallback();
Expand Down
12 changes: 5 additions & 7 deletions apps/app/src/media-note/link-click/opened.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import type { Workspace, WorkspaceLeaf } from "obsidian";
import type { MediaEmbedViewState } from "@/media-view/iframe-view";
import type { MediaUrlViewState } from "@/media-view/url-view";
import type { MediaWebpageViewState } from "@/media-view/webpage-view";
import type { UrlMediaInfo } from "./external";
import { isFileMediaInfo, type FileMediaInfo } from "./internal";
import type { MediaInfo } from "../manager";
import { isFileMediaInfo, type FileMediaInfo } from "../manager/file-info";
import type { UrlMediaInfo } from "../manager/url-info";

function filterFileLeaf(leaf: WorkspaceLeaf, info: FileMediaInfo) {
const { file: filePath } = leaf.view.getState() as { file: string };
Expand All @@ -18,10 +19,7 @@ function filterUrlLeaf(leaf: WorkspaceLeaf, info: UrlMediaInfo) {
return source && info.isSameSource(source);
}

export function getLeavesOfMedia(
info: UrlMediaInfo | FileMediaInfo,
workspace: Workspace,
) {
export function getLeavesOfMedia(info: MediaInfo, workspace: Workspace) {
return workspace.getLeavesOfType(info.viewType).filter((leaf) => {
if (isFileMediaInfo(info)) {
return filterFileLeaf(leaf, info);
Expand All @@ -36,7 +34,7 @@ export function updateHash(hash: string, leaf: WorkspaceLeaf) {
}

export function openInOpenedPlayer(
info: FileMediaInfo | UrlMediaInfo,
info: MediaInfo,
workspace: Workspace,
): boolean {
const opened = getLeavesOfMedia(info, workspace);
Expand Down
17 changes: 17 additions & 0 deletions apps/app/src/media-note/manager/file-info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { TFile } from "obsidian";
import {
isMediaFileViewType,
type MediaFileViewType,
} from "@/media-view/file-view";
import type { MediaType } from "@/patch/utils";

export interface FileMediaInfo {
viewType: MediaFileViewType;
type: MediaType;
file: TFile;
hash: string;
}

export function isFileMediaInfo(info: unknown): info is FileMediaInfo {
return isMediaFileViewType((info as FileMediaInfo).viewType);
}
Loading

0 comments on commit 5d6ae4f

Please sign in to comment.