mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-12-08 16:27:31 +00:00
feat: add form api
This commit is contained in:
parent
fe83f50286
commit
6da7fb7ac3
@ -202,16 +202,27 @@ class AuthEndpoint {
|
||||
class CoreEndpoint {
|
||||
async checkUpdate() {
|
||||
console.log(globalThis);
|
||||
const webview = await WebView.create("https://spotube.krtirtho.dev");
|
||||
webview.onUrlChange((url) => {
|
||||
console.log("url_request: ", url);
|
||||
if (url.includes("/about")) {
|
||||
webview.close();
|
||||
// const webview = await WebView.create("https://spotube.krtirtho.dev");
|
||||
// webview.onUrlChange((url) => {
|
||||
// console.log("url_request: ", url);
|
||||
// if (url.includes("/about")) {
|
||||
// webview.close();
|
||||
// }
|
||||
// });
|
||||
// await webview.open();
|
||||
const res = await SpotubeForm.show("Hello", [
|
||||
{
|
||||
objectType: "input",
|
||||
id: "email",
|
||||
variant: "text",
|
||||
placeholder: "Enter your email",
|
||||
defaultValue: null,
|
||||
required: true,
|
||||
regex: null,
|
||||
}
|
||||
});
|
||||
await webview.open();
|
||||
])
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 5000));
|
||||
console.log("Form Result: ", res);
|
||||
}
|
||||
}
|
||||
class Plugin {
|
||||
|
||||
@ -3,6 +3,7 @@ import 'package:shelf/shelf.dart';
|
||||
import 'package:shelf_router/shelf_router.dart';
|
||||
import 'package:spotube/provider/server/routes/connect.dart';
|
||||
import 'package:spotube/provider/server/routes/playback.dart';
|
||||
import 'package:spotube/provider/server/routes/plugin_apis/form.dart';
|
||||
import 'package:spotube/provider/server/routes/plugin_apis/webview.dart';
|
||||
|
||||
Handler pluginApiAuthMiddleware(Handler handler) {
|
||||
@ -20,6 +21,7 @@ final serverRouterProvider = Provider((ref) {
|
||||
final playbackRoutes = ref.watch(serverPlaybackRoutesProvider);
|
||||
final connectRoutes = ref.watch(serverConnectRoutesProvider);
|
||||
final webviewRoutes = ref.watch(serverWebviewRoutesProvider);
|
||||
final formRoutes = ref.watch(serverFormRoutesProvider);
|
||||
|
||||
final router = Router();
|
||||
|
||||
@ -52,6 +54,10 @@ final serverRouterProvider = Provider((ref) {
|
||||
"/plugin-api/webview/cookies",
|
||||
pluginApiAuthMiddleware(webviewRoutes.postGetWebviewCookies),
|
||||
);
|
||||
router.post(
|
||||
"/plugin-api/form/show",
|
||||
pluginApiAuthMiddleware(formRoutes.showForm),
|
||||
);
|
||||
|
||||
router.all("/ws", connectRoutes.websocket);
|
||||
|
||||
|
||||
30
lib/provider/server/routes/plugin_apis/form.dart
Normal file
30
lib/provider/server/routes/plugin_apis/form.dart
Normal file
@ -0,0 +1,30 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:riverpod/riverpod.dart';
|
||||
import 'package:shelf/shelf.dart';
|
||||
import 'package:spotube/collections/routes.dart';
|
||||
import 'package:spotube/collections/routes.gr.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
|
||||
class ServerFormRoutes {
|
||||
Future<Response> showForm(Request request) async {
|
||||
final body = jsonDecode(await request.readAsString());
|
||||
final res = await rootNavigatorKey.currentContext!.router
|
||||
.push<List<Map<String, dynamic>>?>(
|
||||
SettingsMetadataProviderFormRoute(
|
||||
title: body["title"],
|
||||
fields: (body["fields"] as List)
|
||||
.map((e) => MetadataFormFieldObject.fromJson(e))
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
|
||||
return Response.ok(
|
||||
jsonEncode(res),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final serverFormRoutesProvider = Provider((ref) => ServerFormRoutes());
|
||||
@ -82,7 +82,7 @@ packages:
|
||||
source: hosted
|
||||
version: "1.6.5"
|
||||
async:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: async
|
||||
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
|
||||
|
||||
@ -162,6 +162,7 @@ dependencies:
|
||||
flutter_rust_bridge: 2.11.1
|
||||
json_annotation: ^4.9.0
|
||||
random_user_agents: ^1.0.18
|
||||
async: ^2.13.0
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.4.13
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use std::fmt::format;
|
||||
use crate::api::plugin::commands::PluginCommand;
|
||||
use crate::api::plugin::executors::{
|
||||
execute_albums, execute_artists, execute_audio_source, execute_auth, execute_browse,
|
||||
@ -11,7 +12,8 @@ use crate::api::plugin::senders::{
|
||||
PluginTrackSender, PluginUserSender,
|
||||
};
|
||||
use crate::frb_generated::StreamSink;
|
||||
use crate::internal::apis::webview;
|
||||
use crate::internal::apis;
|
||||
use crate::internal::apis::{form, webview};
|
||||
use anyhow::anyhow;
|
||||
use flutter_rust_bridge::{frb, Rust2DartSendError};
|
||||
use llrt_modules::module_builder::ModuleBuilder;
|
||||
@ -51,7 +53,9 @@ async fn create_context(
|
||||
.with_global(navigator::init)
|
||||
.with_global(url::init)
|
||||
.with_global(timers::init)
|
||||
.with_global(util::init);
|
||||
.with_global(util::init)
|
||||
.with_global(form::init)
|
||||
.with_global(webview::init);
|
||||
|
||||
let (module_resolver, module_loader, global_attachment) = module_builder.build();
|
||||
runtime
|
||||
@ -63,8 +67,8 @@ async fn create_context(
|
||||
.expect("Unable to create async context");
|
||||
|
||||
async_with!(context => |ctx| {
|
||||
apis::init(&ctx, server_endpoint_url, server_secret)?;
|
||||
global_attachment.attach(&ctx).catch(&ctx).map_err(|e| anyhow!("Failed to attach global modules: {}", e))?;
|
||||
webview::init(&ctx, server_endpoint_url, server_secret).catch(&ctx).map_err(|e| anyhow!("Failed to initialize WebView API: {}", e))?;
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.await
|
||||
|
||||
25
rust/src/internal/apis/form.rs
Normal file
25
rust/src/internal/apis/form.rs
Normal file
@ -0,0 +1,25 @@
|
||||
use rquickjs::{Ctx, Value};
|
||||
|
||||
pub fn init(ctx: &Ctx) -> rquickjs::Result<()> {
|
||||
ctx.eval::<Value, _>(
|
||||
r#"
|
||||
globalThis.SpotubeForm = class SpotubeForm {
|
||||
static async show(title, fields) {
|
||||
return await fetch(
|
||||
`${__serverUrl}/plugin-api/form/show`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Plugin-Secret': __serverSecret,
|
||||
},
|
||||
body: JSON.stringify({ title, fields }),
|
||||
}
|
||||
).then(res=>res.json());
|
||||
}
|
||||
}
|
||||
"#,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -1,2 +1,11 @@
|
||||
use rquickjs::Ctx;
|
||||
|
||||
pub mod event_source;
|
||||
pub mod form;
|
||||
pub mod webview;
|
||||
|
||||
pub fn init(ctx: &Ctx, endpoint_url: String, secret: String) -> rquickjs::Result<()> {
|
||||
ctx.globals().set("__serverUrl", endpoint_url)?;
|
||||
ctx.globals().set("__serverSecret", secret)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -52,8 +52,8 @@ impl<'js> WebView<'js> {
|
||||
|
||||
#[qjs(static)]
|
||||
pub async fn create(ctx: Ctx<'js>, url: String) -> rquickjs::Result<Class<'js, WebView<'js>>> {
|
||||
let endpoint_url: String = ctx.globals().get("__webviewUrl").unwrap_or_default();
|
||||
let secret: String = ctx.globals().get("__webviewSecret").unwrap_or_default();
|
||||
let endpoint_url: String = ctx.globals().get("__serverUrl").unwrap_or_default();
|
||||
let secret: String = ctx.globals().get("__serverSecret").unwrap_or_default();
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let endpoint = format!("{}/plugin-api/webview/create", endpoint_url.clone());
|
||||
@ -203,12 +203,9 @@ impl<'js> WebView<'js> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(ctx: &Ctx, endpoint_url: String, secret: String) -> rquickjs::Result<()> {
|
||||
// Store config in globals for access in static methods
|
||||
ctx.globals().set("__webviewUrl", endpoint_url)?;
|
||||
ctx.globals().set("__webviewSecret", secret)?;
|
||||
|
||||
// Register the WebView class
|
||||
|
||||
pub fn init(ctx: &Ctx) -> rquickjs::Result<()> {
|
||||
Class::<WebView>::define(&ctx.globals())?;
|
||||
|
||||
Ok(())
|
||||
|
||||
Loading…
Reference in New Issue
Block a user