Skip to content

Commit

Permalink
Add basic history page
Browse files Browse the repository at this point in the history
  • Loading branch information
probablykasper committed Jan 21, 2024
1 parent 7ce701b commit 04e39aa
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Changelog

## Next
- Add basic history page, accessible via `Cmd/Ctrl+Y`.
- Fix selection staying in the same position when videos update
- Keep video selected if it moves position
- Fix settings link in Get Started popup
Expand Down
6 changes: 6 additions & 0 deletions bindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ export function checkNow() {
return invoke()<null>("check_now")
}

export function getHistory() {
return invoke()<UndoHistory>("get_history")
}

export function getVideos(options: Options, after: After | null) {
return invoke()<Video[]>("get_videos", { options,after })
}
Expand All @@ -55,4 +59,6 @@ export type Options = { show_all: boolean; show_archived: boolean; channel_filte
export type Video = { id: string; title: string; description: string; publishTimeMs: number; durationMs: number; thumbnailStandard: boolean; thumbnailMaxres: boolean; channelId: string; channelName: string; unread: boolean; archived: boolean }
export type After = { publishTimeMs: number; id: string }
export type Channel = { id: string; name: string; icon: string; uploads_playlist_id: string; from_time: number; refresh_rate_ms: number; tags: string[] }
export type UndoHistory = { entries: ([number, Action])[] }
export type AddChannelOptions = { url: string; from_time: number; refresh_rate_ms: number; tags: string[] }
export type Action = "CheckNow" | { Archive: string } | { Unarchive: string } | { AddChannel: string } | { UpdateOrDeleteChannels: string }
50 changes: 48 additions & 2 deletions src-tauri/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ use crate::settings::{Channel, Settings, VersionedSettings};
use crate::{api, background, throw};
use atomicwrites::{AtomicFile, OverwriteBehavior};
use scraper::{Html, Selector};
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use specta::Type;
use sqlx::SqlitePool;
use std::collections::HashSet;
use std::convert::TryInto;
use std::env;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH};
use tauri::{command, Config, State};
use tokio::sync::Mutex;
use url::Url;
Expand Down Expand Up @@ -41,6 +43,7 @@ pub struct Data {
pub versioned_settings: VersionedSettings,
pub paths: AppPaths,
pub window: tauri::Window,
pub user_history: UndoHistory,
}
impl Data {
pub fn settings(&mut self) -> &mut Settings {
Expand Down Expand Up @@ -122,6 +125,7 @@ pub async fn tags(data: DataState<'_>) -> Result<Vec<String>, String> {
pub async fn check_now(data: DataState<'_>) -> Result<(), String> {
let mut data = data.0.lock().await;
data.check_now()?;
data.user_history.push(Action::CheckNow);
Ok(())
}

Expand Down Expand Up @@ -227,6 +231,8 @@ pub async fn set_channels(channels: Vec<Channel>, data: DataState<'_>) -> Result
let mut data = data.0.lock().await;
data.settings().channels = channels;
data.save_settings()?;
data.user_history
.push(Action::UpdateOrDeleteChannels("".to_string()));
Ok(())
}

Expand Down Expand Up @@ -256,7 +262,7 @@ pub async fn add_channel(options: AddChannelOptions, data: DataState<'_>) -> Res
};

settings.channels.push(Channel {
id: channel.id,
id: channel.id.clone(),
name: channel.snippet.title,
icon: channel.snippet.thumbnails.medium.url,
uploads_playlist_id: channel.contentDetails.relatedPlaylists.uploads,
Expand All @@ -265,6 +271,7 @@ pub async fn add_channel(options: AddChannelOptions, data: DataState<'_>) -> Res
tags: options.tags,
});
data.save_settings()?;
data.user_history.push(Action::AddChannel(channel.id));
Ok(())
}

Expand All @@ -291,3 +298,42 @@ impl ArcData {
Self(Arc::new(Mutex::new(data)))
}
}

#[derive(Serialize, Clone, Type)]
pub struct UndoHistory {
pub entries: Vec<(u32, Action)>,
}

impl UndoHistory {
pub fn new() -> Self {
Self { entries: vec![] }
}
pub fn push(&mut self, action: Action) {
let time: u32 = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs()
.try_into()
.unwrap();
self.entries.push((time, action));
if self.entries.len() > 100 {
self.entries.remove(0);
}
}
}

#[derive(Serialize, Clone, Type)]
pub enum Action {
CheckNow,
Archive(String),
Unarchive(String),
AddChannel(String),
UpdateOrDeleteChannels(String),
}

#[command]
#[specta::specta]
pub async fn get_history(data: DataState<'_>) -> Result<UndoHistory, String> {
let data = data.0.lock().await;
Ok(data.user_history.clone())
}
14 changes: 9 additions & 5 deletions src-tauri/src/db.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::api::playlist_items;
use crate::data::{AppPaths, DataState};
use crate::data::{Action, AppPaths, DataState};
use crate::throw;
use serde::{Deserialize, Serialize};
use specta::Type;
Expand Down Expand Up @@ -225,19 +225,23 @@ async fn set_archived(pool: &SqlitePool, id: &str, value: bool) -> Result<(), St
#[command]
#[specta::specta]
pub async fn archive(id: String, data: DataState<'_>) -> Result<(), String> {
let data = data.0.lock().await;
let mut data = data.0.lock().await;
match set_archived(&data.db_pool, &id, true).await {
Ok(()) => Ok(()),
Ok(()) => (),
Err(e) => throw!("Error archiving video: {}", e),
}
data.user_history.push(Action::Archive(id));
Ok(())
}

#[command]
#[specta::specta]
pub async fn unarchive(id: String, data: DataState<'_>) -> Result<(), String> {
let data = data.0.lock().await;
let mut data = data.0.lock().await;
match set_archived(&data.db_pool, &id, false).await {
Ok(()) => Ok(()),
Ok(()) => (),
Err(e) => throw!("Error unarchiving video: {}", e),
}
data.user_history.push(Action::Unarchive(id));
Ok(())
}
8 changes: 8 additions & 0 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use crate::data::{AppPaths, ArcData, Data};
use crate::settings::yt_email_notifier;
use crate::settings::VersionedSettings;
use data::UndoHistory;
use tauri::api::{dialog, shell};
#[cfg(target_os = "macos")]
use tauri::AboutMetadata;
Expand Down Expand Up @@ -93,6 +94,7 @@ async fn main() {
data::add_channel,
data::set_general_settings,
data::check_now,
data::get_history,
db::get_videos,
db::archive,
db::unarchive
Expand Down Expand Up @@ -137,6 +139,7 @@ async fn main() {
data::add_channel,
data::set_general_settings,
data::check_now,
data::get_history,
db::get_videos,
db::archive,
db::unarchive,
Expand Down Expand Up @@ -184,6 +187,7 @@ async fn main() {
versioned_settings: settings,
paths: app_paths,
window: win.clone(),
user_history: UndoHistory::new(),
};
app.manage(ArcData::new(data));

Expand Down Expand Up @@ -269,6 +273,10 @@ async fn main() {
.accelerator("Alt+CmdOrCtrl+A")
.into(),
MenuItem::Separator.into(),
CustomMenuItem::new("History", "History")
.accelerator("CmdOrCtrl+Y")
.into(),
MenuItem::Separator.into(),
MenuItem::EnterFullScreen.into(),
]),
)),
Expand Down
1 change: 1 addition & 0 deletions src/lib/Link.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<style lang="sass">
button
font-size: 13px
font-size: inherit
margin: 0px
background-color: transparent
padding: 0px
Expand Down
2 changes: 1 addition & 1 deletion src/lib/modals/Settings.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<p class="sub">
Kadium has a default API key, but it's vulnerable to abuse and could run out of quota.
<Link on:click={() => (keyGuideVisible = true)}>
<div>Get your own key</div>
<div style="font-size: 13px;">Get your own key</div>
</Link>
</p>
<input class="textbox" type="text" bind:value={apiKey} placeholder="AIzaSyNq5Y9knL..." />
Expand Down
2 changes: 2 additions & 0 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
goto('/', { replaceState: true })
} else if (payload === 'Channels') {
goto('/channels', { replaceState: true })
} else if (payload === 'History') {
goto('/history', { replaceState: true })
} else if (payload === 'Preferences...' || payload === 'Options...') {
$settingsOpen = true
} else if (payload === 'Add Channel...') {
Expand Down
1 change: 1 addition & 0 deletions src/routes/channels/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@
color: hsla(231, 20%, 100%, 0.5)
.edit
padding: 10px 0px
font-size: 13px
input
height: 28px
box-sizing: border-box
Expand Down
69 changes: 69 additions & 0 deletions src/routes/history/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<script lang="ts">
import { addChannel, getHistory } from '../../../bindings'

Check failure on line 2 in src/routes/history/+page.svelte

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest)

'addChannel' is defined but never used
import Link from '$lib/Link.svelte'
import { shell } from '@tauri-apps/api'
const history = getHistory()
</script>

<main>
<h1>Basic-ass history page</h1>

<p class="dark">The history is lost when you close the app</p>

{#await history then history}
{#if history.entries.length === 0}
Empty! When you do things, it will show here.
{/if}
<table>
{#each history.entries.reverse() as [timestamp, action]}
<tr>
<td class="timestamp dark">
{new Date(timestamp * 1000).toLocaleString()}
</td>
<td>
{#if action === 'CheckNow'}
Manually check for videos
{:else if 'Archive' in action}
{@const id = action.Archive}
Archive video ID <Link
on:click={() => shell.open(`https://www.youtube.com/watch?v=${id}`)}
>{action.Archive}</Link
>
{:else if 'Unarchive' in action}
{@const id = action.Unarchive}
Unarchive video ID <Link
on:click={() => shell.open(`https://www.youtube.com/watch?v=${id}`)}
>{action.Unarchive}</Link
>
{:else if 'AddChannel' in action}
{@const id = action.AddChannel}
Added channel <Link
on:click={() => shell.open(`https://www.youtube.com/channel/${id}`)}
>{action.AddChannel}</Link
>
{:else if 'UpdateOrDeleteChannels' in action}
Updated or deleted channel(s)
{/if}
</td>
</tr>
{/each}
</table>
{#if history.entries.length >= 100}
<p>The end. Only 100 entries are shown.</p>
{/if}
{:catch error}
Error {error}
{/await}
</main>

<style lang="sass">
main
padding: 20px
padding-top: 0px
overflow-y: auto
.dark
color: hsl(210, 8%, 80%)
.timestamp
padding-right: 10px
</style>

0 comments on commit 04e39aa

Please sign in to comment.