mirror of
https://github.com/Xinrea/bili-shadowreplay.git
synced 2025-11-25 04:22:24 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3bb014644 |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "bili-shadowreplay",
|
||||
"private": true,
|
||||
"version": "2.7.0",
|
||||
"version": "2.7.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -20,15 +20,31 @@ pub struct VideoRow {
|
||||
pub platform: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, sqlx::FromRow)]
|
||||
pub struct VideoNoCover {
|
||||
pub id: i64,
|
||||
pub room_id: u64,
|
||||
pub file: String,
|
||||
pub length: i64,
|
||||
pub size: i64,
|
||||
pub status: i64,
|
||||
pub bvid: String,
|
||||
pub title: String,
|
||||
pub desc: String,
|
||||
pub tags: String,
|
||||
pub area: i64,
|
||||
pub created_at: String,
|
||||
pub platform: String,
|
||||
}
|
||||
|
||||
impl Database {
|
||||
pub async fn get_videos(&self, room_id: u64) -> Result<Vec<VideoRow>, DatabaseError> {
|
||||
pub async fn get_videos(&self, room_id: u64) -> Result<Vec<VideoNoCover>, DatabaseError> {
|
||||
let lock = self.db.read().await.clone().unwrap();
|
||||
Ok(
|
||||
sqlx::query_as::<_, VideoRow>("SELECT * FROM videos WHERE room_id = $1;")
|
||||
.bind(room_id as i64)
|
||||
.fetch_all(&lock)
|
||||
.await?,
|
||||
)
|
||||
let videos = sqlx::query_as::<_, VideoNoCover>("SELECT * FROM videos WHERE room_id = $1;")
|
||||
.bind(room_id as i64)
|
||||
.fetch_all(&lock)
|
||||
.await?;
|
||||
Ok(videos)
|
||||
}
|
||||
|
||||
pub async fn get_video(&self, id: i64) -> Result<VideoRow, DatabaseError> {
|
||||
@@ -100,12 +116,21 @@ impl Database {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_all_videos(&self) -> Result<Vec<VideoRow>, DatabaseError> {
|
||||
pub async fn get_all_videos(&self) -> Result<Vec<VideoNoCover>, DatabaseError> {
|
||||
let lock = self.db.read().await.clone().unwrap();
|
||||
Ok(
|
||||
sqlx::query_as::<_, VideoRow>("SELECT * FROM videos ORDER BY created_at DESC;")
|
||||
let videos =
|
||||
sqlx::query_as::<_, VideoNoCover>("SELECT * FROM videos ORDER BY created_at DESC;")
|
||||
.fetch_all(&lock)
|
||||
.await?,
|
||||
)
|
||||
.await?;
|
||||
Ok(videos)
|
||||
}
|
||||
|
||||
pub async fn get_video_cover(&self, id: i64) -> Result<String, DatabaseError> {
|
||||
let lock = self.db.read().await.clone().unwrap();
|
||||
let video = sqlx::query_as::<_, VideoRow>("SELECT * FROM videos WHERE id = $1")
|
||||
.bind(id)
|
||||
.fetch_one(&lock)
|
||||
.await?;
|
||||
Ok(video.cover)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::database::task::TaskRow;
|
||||
use crate::database::video::VideoRow;
|
||||
use crate::database::video::{VideoNoCover, VideoRow};
|
||||
use crate::ffmpeg;
|
||||
use crate::handlers::utils::get_disk_info_inner;
|
||||
use crate::progress_reporter::{
|
||||
@@ -301,7 +301,7 @@ pub async fn get_video(state: state_type!(), id: i64) -> Result<VideoRow, String
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "gui", tauri::command)]
|
||||
pub async fn get_videos(state: state_type!(), room_id: u64) -> Result<Vec<VideoRow>, String> {
|
||||
pub async fn get_videos(state: state_type!(), room_id: u64) -> Result<Vec<VideoNoCover>, String> {
|
||||
state
|
||||
.db
|
||||
.get_videos(room_id)
|
||||
@@ -310,10 +310,19 @@ pub async fn get_videos(state: state_type!(), room_id: u64) -> Result<Vec<VideoR
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "gui", tauri::command)]
|
||||
pub async fn get_all_videos(state: state_type!()) -> Result<Vec<VideoRow>, String> {
|
||||
pub async fn get_all_videos(state: state_type!()) -> Result<Vec<VideoNoCover>, String> {
|
||||
state.db.get_all_videos().await.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "gui", tauri::command)]
|
||||
pub async fn get_video_cover(state: state_type!(), id: i64) -> Result<String, String> {
|
||||
state
|
||||
.db
|
||||
.get_video_cover(id)
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "gui", tauri::command)]
|
||||
pub async fn delete_video(state: state_type!(), id: i64) -> Result<(), String> {
|
||||
// get video info from dbus
|
||||
|
||||
@@ -3,8 +3,12 @@ use std::fmt::{self, Display};
|
||||
use crate::{
|
||||
config::Config,
|
||||
database::{
|
||||
account::AccountRow, message::MessageRow, record::RecordRow, recorder::RecorderRow,
|
||||
task::TaskRow, video::VideoRow,
|
||||
account::AccountRow,
|
||||
message::MessageRow,
|
||||
record::RecordRow,
|
||||
recorder::RecorderRow,
|
||||
task::TaskRow,
|
||||
video::{VideoNoCover, VideoRow},
|
||||
},
|
||||
handlers::{
|
||||
account::{
|
||||
@@ -27,8 +31,8 @@ use crate::{
|
||||
utils::{console_log, get_disk_info, DiskInfo},
|
||||
video::{
|
||||
cancel, clip_range, delete_video, encode_video_subtitle, generate_video_subtitle,
|
||||
get_all_videos, get_video, get_video_subtitle, get_video_typelist, get_videos,
|
||||
update_video_cover, update_video_subtitle, upload_procedure,
|
||||
get_all_videos, get_video, get_video_cover, get_video_subtitle, get_video_typelist,
|
||||
get_videos, update_video_cover, update_video_subtitle, upload_procedure,
|
||||
},
|
||||
AccountInfo,
|
||||
},
|
||||
@@ -656,21 +660,36 @@ async fn handler_get_video(
|
||||
struct GetVideosRequest {
|
||||
room_id: u64,
|
||||
}
|
||||
|
||||
async fn handler_get_videos(
|
||||
state: axum::extract::State<State>,
|
||||
Json(param): Json<GetVideosRequest>,
|
||||
) -> Result<Json<ApiResponse<Vec<VideoRow>>>, ApiError> {
|
||||
) -> Result<Json<ApiResponse<Vec<VideoNoCover>>>, ApiError> {
|
||||
let videos = get_videos(state.0, param.room_id).await?;
|
||||
Ok(Json(ApiResponse::success(videos)))
|
||||
}
|
||||
|
||||
async fn handler_get_all_videos(
|
||||
state: axum::extract::State<State>,
|
||||
) -> Result<Json<ApiResponse<Vec<VideoRow>>>, ApiError> {
|
||||
) -> Result<Json<ApiResponse<Vec<VideoNoCover>>>, ApiError> {
|
||||
let videos = get_all_videos(state.0).await?;
|
||||
Ok(Json(ApiResponse::success(videos)))
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct GetVideoCoverRequest {
|
||||
id: i64,
|
||||
}
|
||||
|
||||
async fn handler_get_video_cover(
|
||||
state: axum::extract::State<State>,
|
||||
Json(param): Json<GetVideoCoverRequest>,
|
||||
) -> Result<Json<ApiResponse<String>>, ApiError> {
|
||||
let video_cover = get_video_cover(state.0, param.id).await?;
|
||||
Ok(Json(ApiResponse::success(video_cover)))
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct DeleteVideoRequest {
|
||||
@@ -1236,6 +1255,7 @@ pub async fn start_api_server(state: State) {
|
||||
.route("/api/clip_range", post(handler_clip_range))
|
||||
.route("/api/get_video", post(handler_get_video))
|
||||
.route("/api/get_videos", post(handler_get_videos))
|
||||
.route("/api/get_video_cover", post(handler_get_video_cover))
|
||||
.route("/api/get_all_videos", post(handler_get_all_videos))
|
||||
.route("/api/get_video_typelist", post(handler_get_video_typelist))
|
||||
.route("/api/get_video_subtitle", post(handler_get_video_subtitle))
|
||||
|
||||
@@ -433,6 +433,7 @@ fn setup_invoke_handlers(builder: tauri::Builder<tauri::Wry>) -> tauri::Builder<
|
||||
crate::handlers::video::get_video,
|
||||
crate::handlers::video::get_videos,
|
||||
crate::handlers::video::get_all_videos,
|
||||
crate::handlers::video::get_video_cover,
|
||||
crate::handlers::video::delete_video,
|
||||
crate::handlers::video::get_video_typelist,
|
||||
crate::handlers::video::update_video_cover,
|
||||
|
||||
@@ -213,15 +213,19 @@
|
||||
});
|
||||
}
|
||||
|
||||
function find_video(e) {
|
||||
async function find_video(e) {
|
||||
if (!e.target) {
|
||||
selected_video = null;
|
||||
return;
|
||||
}
|
||||
const id = parseInt(e.target.value);
|
||||
selected_video = videos.find((v) => {
|
||||
let target_video = videos.find((v) => {
|
||||
return v.value == id;
|
||||
});
|
||||
if (target_video) {
|
||||
target_video.cover = await invoke("get_video_cover", { id: id });
|
||||
}
|
||||
selected_video = target_video;
|
||||
console.log("video selected", videos, selected_video, e, id);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
await loadVideos();
|
||||
});
|
||||
|
||||
let cover_cache: Map<number, string> = new Map();
|
||||
|
||||
async function loadVideos() {
|
||||
loading = true;
|
||||
try {
|
||||
@@ -44,6 +46,16 @@
|
||||
const roomIdsSet = new Set<number>();
|
||||
const platformsSet = new Set<string>();
|
||||
const tempVideos = await invoke<VideoItem[]>("get_all_videos");
|
||||
for (const video of tempVideos) {
|
||||
if (cover_cache.has(video.id)) {
|
||||
video.cover = cover_cache.get(video.id) || "";
|
||||
} else {
|
||||
video.cover = await invoke<string>("get_video_cover", {
|
||||
id: video.id,
|
||||
});
|
||||
cover_cache.set(video.id, video.cover);
|
||||
}
|
||||
}
|
||||
|
||||
for (const video of tempVideos) {
|
||||
roomIdsSet.add(video.room_id);
|
||||
@@ -536,15 +548,11 @@
|
||||
<div
|
||||
class="w-12 h-8 rounded-lg overflow-hidden bg-gray-100 dark:bg-gray-700 flex items-center justify-center flex-shrink-0"
|
||||
>
|
||||
{#if video.cover}
|
||||
<img
|
||||
src={video.cover}
|
||||
alt="封面"
|
||||
class="w-full h-full object-cover"
|
||||
/>
|
||||
{:else}
|
||||
<Video class="w-4 h-4 text-gray-400" />
|
||||
{/if}
|
||||
<img
|
||||
src={video.cover}
|
||||
alt="封面"
|
||||
class="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div class="min-w-0 flex-1 w-64">
|
||||
<p
|
||||
|
||||
Reference in New Issue
Block a user