Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
# top-most EditorConfig file
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = tab
indent_size = 4
tab_width = 4
# top-most EditorConfig file
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = tab
indent_size = 4
tab_width = 4

[*.{yaml,yml}]
indent_style = space
indent_size = 2
2 changes: 1 addition & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
github: chhoumann
custom: https://www.buymeacoffee.com/chhoumann
custom: https://www.buymeacoffee.com/chhoumann
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
workflow_dispatch:
inputs:
dryRun:
description: 'Dry run (no actual release)'
description: "Dry run (no actual release)"
required: false
default: false
type: boolean
Expand Down
11 changes: 10 additions & 1 deletion .oxfmtrc.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"useTabs": true,
"ignorePatterns": []
"ignorePatterns": [],
"overrides": [
{
"files": ["**/*.yaml", "**/*.yml"],
"options": {
"tabWidth": 2,
"useTabs": false
}
}
]
}
30 changes: 15 additions & 15 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ site_name: PodNotes
repo_url: https://github.com/chhoumann/podnotes
edit_uri: edit/master/docs/docs
nav:
- Home: index.md
- Commands: commands.md
- Podcasts: podcasts.md
- 'Local files': local_files.md
- "Import & Export": import_export.md
- Transcripts: transcripts.md
- 'Notes':
- Timestamps: timestamps.md
- Templates: templates.md
- Advanced:
- API: api.md
- Usage with QuickAdd: QuickAdd.md
- Home: index.md
- Commands: commands.md
- Podcasts: podcasts.md
- "Local files": local_files.md
- "Import & Export": import_export.md
- Transcripts: transcripts.md
- "Notes":
- Timestamps: timestamps.md
- Templates: templates.md
- Advanced:
- API: api.md
- Usage with QuickAdd: QuickAdd.md
theme:
name: material
palette:
primary: blue
name: material
palette:
primary: blue
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"build": "npm run typecheck && vite build",
"typecheck": "tsc --noEmit",
"lint": "oxlint --deny-warnings src tests/e2e scripts",
"format:check": "oxfmt --check package.json manifest.json tsconfig.json .oxlintrc.json .oxfmtrc.json vite.config.ts vitest.config.ts vitest.e2e.config.ts tests/e2e scripts",
"format:check": "npm run format -- --check",
"version": "node version-bump.mjs && git add manifest.json versions.json",
"semantic-release": "semantic-release",
"test": "npm run check:a11y && vitest",
Expand All @@ -27,7 +27,7 @@
"check:a11y": "svelte-check --fail-on-warnings",
"docs:build": "mkdocs build -f docs/mkdocs.yml -d site",
"docs:deploy": "npm run docs:build && wrangler pages deploy docs/site --project-name podnotes --branch master",
"format": "oxfmt package.json manifest.json tsconfig.json .oxlintrc.json .oxfmtrc.json vite.config.ts vitest.config.ts vitest.e2e.config.ts tests/e2e scripts"
"format": "oxfmt src tests scripts .github package.json manifest.json versions.json tsconfig.json .oxlintrc.json .oxfmtrc.json vite.config.ts vitest.config.ts vitest.e2e.config.ts vitest.setup.ts version-bump.mjs wrangler.jsonc orca.yaml docs/mkdocs.yml"
},
"dependencies": {
"fuse.js": "^7.4.2",
Expand Down
24 changes: 7 additions & 17 deletions src/API/API.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,14 @@ describe("API.getPodcastSegmentFormatted", () => {
currentEpisode.set(feedEpisode);
const api = new API();

expect(api.getPodcastSegmentFormatted("HH:mm:ss", 115, 125)).toBe(
"00:01:55-00:02:05",
);
expect(api.getPodcastSegmentFormatted("HH:mm:ss", 115, 125)).toBe("00:01:55-00:02:05");
});

test("links feed episodes with start and end times", () => {
currentEpisode.set(feedEpisode);
const api = new API();

const rendered = api.getPodcastSegmentFormatted(
"HH:mm:ss",
115,
125,
true,
);
const rendered = api.getPodcastSegmentFormatted("HH:mm:ss", 115, 125, true);

expect(rendered).toContain("[00:01:55-00:02:05]");
expect(rendered).toContain("time=115");
Expand Down Expand Up @@ -106,9 +99,9 @@ describe("API.getPodcastSegmentFormatted", () => {
expect(api.getPodcastSegmentFormatted("HH:mm:ss", 126, 125, true)).toBe(
"00:02:06-00:02:05",
);
expect(
api.getPodcastSegmentFormatted("HH:mm:ss", 125, Number.NaN, true),
).toBe("00:02:05-00:00:00");
expect(api.getPodcastSegmentFormatted("HH:mm:ss", 125, Number.NaN, true)).toBe(
"00:02:05-00:00:00",
);
});

test("seeking through the public API clears an active playback segment", () => {
Expand Down Expand Up @@ -263,12 +256,9 @@ describe("API volume (AP-07)", () => {

describe("API transcript access", () => {
function setTranscriptVault(files: Record<string, string>) {
const createTFile = (path: string): TFile =>
Object.assign(new TFile(), { path });
const createTFile = (path: string): TFile => Object.assign(new TFile(), { path });
const getAbstractFileByPath = vi.fn((path: string) =>
Object.prototype.hasOwnProperty.call(files, path)
? createTFile(path)
: null,
Object.prototype.hasOwnProperty.call(files, path) ? createTFile(path) : null,
);
const read = vi.fn(async (file: TFile) => files[file.path] ?? "");

Expand Down
54 changes: 12 additions & 42 deletions src/API/API.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ import {
import { get } from "svelte/store";
import encodePodnotesURI from "src/utility/encodePodnotesURI";
import { isLocalFile } from "src/utility/isLocalFile";
import {
formatPodcastSegment,
normalizePodcastSegmentTimes,
} from "src/utility/podcastSegment";
import { formatPodcastSegment, normalizePodcastSegmentTimes } from "src/utility/podcastSegment";
import {
adjustPlaybackRate,
normalizePlaybackRate,
Expand All @@ -39,12 +36,8 @@ const normalizeSkipLength = (length: number): number =>
// two-way binds the store onto the media element. Fall back to the current value
// (itself clamped) so a bad write is a no-op rather than corrupting playback.
const clampVolume = (value: number, fallback = 1): number => {
const safeFallback = Number.isFinite(fallback)
? Math.min(1, Math.max(0, fallback))
: 1;
return Number.isFinite(value)
? Math.min(1, Math.max(0, value))
: safeFallback;
const safeFallback = Number.isFinite(fallback) ? Math.min(1, Math.max(0, fallback)) : 1;
return Number.isFinite(value) ? Math.min(1, Math.max(0, value)) : safeFallback;
};

export class API implements IAPI {
Expand Down Expand Up @@ -96,11 +89,7 @@ export class API implements IAPI {
* @param offsetSeconds Optional offset to subtract from the current playback time.
* @returns
*/
getPodcastTimeFormatted(
format: string,
linkify = false,
offsetSeconds = 0,
): string {
getPodcastTimeFormatted(format: string, linkify = false, offsetSeconds = 0): string {
if (!this.podcast) {
throw new Error("No podcast loaded");
}
Expand All @@ -118,11 +107,7 @@ export class API implements IAPI {
return time;
}

const url = encodePodnotesURI(
this.podcast.title,
feedUrl,
adjustedTime,
);
const url = encodePodnotesURI(this.podcast.title, feedUrl, adjustedTime);

return `[${time}](${url.href})`;
}
Expand All @@ -139,11 +124,7 @@ export class API implements IAPI {

const segmentTimes = normalizePodcastSegmentTimes(startTime, endTime);
const segment = segmentTimes
? formatPodcastSegment(
segmentTimes.startTime,
segmentTimes.endTime,
format,
)
? formatPodcastSegment(segmentTimes.startTime, segmentTimes.endTime, format)
: formatPodcastSegment(startTime, endTime, format);

if (!linkify || !segmentTimes) return segment;
Expand Down Expand Up @@ -174,8 +155,7 @@ export class API implements IAPI {
episode,
pluginInstance.settings.transcript.path,
);
const transcriptFile =
pluginInstance.app.vault.getAbstractFileByPath(transcriptPath);
const transcriptFile = pluginInstance.app.vault.getAbstractFileByPath(transcriptPath);

if (!(transcriptFile instanceof TFile)) {
return null;
Expand Down Expand Up @@ -204,18 +184,14 @@ export class API implements IAPI {
}

skipBackward(): void {
const skipBackLen = normalizeSkipLength(
get(plugin).settings.skipBackwardLength,
);
const skipBackLen = normalizeSkipLength(get(plugin).settings.skipBackwardLength);
// Never seek before the start. A cleared settings field (NaN/null) falls
// back to the default rather than corrupting currentTime (PB-02).
this.currentTime = Math.max(0, this.currentTime - skipBackLen);
}

skipForward(): void {
const skipForwardLen = normalizeSkipLength(
get(plugin).settings.skipForwardLength,
);
const skipForwardLen = normalizeSkipLength(get(plugin).settings.skipForwardLength);
const target = this.currentTime + skipForwardLen;
const dur = this.length;
// Clamp just short of the end so an over-skip lands at the end instead of
Expand All @@ -224,21 +200,15 @@ export class API implements IAPI {
// not rewind, so keep at least the current time (PB-02 / Codex review #213).
// With an unknown/zero duration (metadata not loaded) leave it unclamped.
this.currentTime =
dur > 0
? Math.max(this.currentTime, Math.min(target, dur - 0.25))
: target;
dur > 0 ? Math.max(this.currentTime, Math.min(target, dur - 0.25)) : target;
}

increasePlaybackRate(): void {
playbackRateStore.update((rate) =>
adjustPlaybackRate(rate, PLAYBACK_RATE_STEP),
);
playbackRateStore.update((rate) => adjustPlaybackRate(rate, PLAYBACK_RATE_STEP));
}

decreasePlaybackRate(): void {
playbackRateStore.update((rate) =>
adjustPlaybackRate(rate, -PLAYBACK_RATE_STEP),
);
playbackRateStore.update((rate) => adjustPlaybackRate(rate, -PLAYBACK_RATE_STEP));
}

resetPlaybackRate(): void {
Expand Down
10 changes: 3 additions & 7 deletions src/API/IAPI.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Episode } from 'src/types/Episode';
import type { Episode } from "src/types/Episode";

export interface IAPI {
readonly podcast: Episode;
Expand All @@ -9,11 +9,7 @@ export interface IAPI {
playbackRate: number;
volume: number;

getPodcastTimeFormatted(
format: string,
linkify?: boolean,
offsetSeconds?: number,
): string;
getPodcastTimeFormatted(format: string, linkify?: boolean, offsetSeconds?: number): string;

getPodcastSegmentFormatted(
format: string,
Expand All @@ -23,7 +19,7 @@ export interface IAPI {
): string;

getTranscript(episode?: Episode): Promise<string | null>;

start(): void;
stop(): void;
togglePlayback(): void;
Expand Down
Loading