mirror of
https://github.com/perstarkse/minne.git
synced 2026-01-18 07:56:44 +01:00
wip: plist ios shortcut
This commit is contained in:
23
Cargo.lock
generated
23
Cargo.lock
generated
@@ -3692,6 +3692,19 @@ version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
||||
|
||||
[[package]]
|
||||
name = "plist"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"indexmap 2.6.0",
|
||||
"quick-xml",
|
||||
"serde",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polling"
|
||||
version = "2.8.0"
|
||||
@@ -3859,6 +3872,15 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick_cache"
|
||||
version = "0.5.2"
|
||||
@@ -6382,6 +6404,7 @@ dependencies = [
|
||||
"minijinja",
|
||||
"minijinja-autoreload",
|
||||
"mockall",
|
||||
"plist",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
|
||||
@@ -21,6 +21,7 @@ mime_guess = "2.0.5"
|
||||
minijinja = { version = "2.5.0", features = ["loader", "multi_template"] }
|
||||
minijinja-autoreload = "2.5.0"
|
||||
mockall = "0.13.0"
|
||||
plist = "1.7.0"
|
||||
serde = { version = "1.0.210", features = ["derive"] }
|
||||
serde_json = "1.0.128"
|
||||
sha2 = "0.10.8"
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -23,7 +23,7 @@ use zettle_db::{
|
||||
ingress::ingress_data, query::query_handler, queue_length::queue_length_handler,
|
||||
},
|
||||
html::{
|
||||
account::{delete_account, set_api_key, show_account_page},
|
||||
account::{delete_account, set_api_key, show_account_page, show_ios_shortcut},
|
||||
documentation::index::show_documentation_index,
|
||||
gdpr::{accept_gdpr, deny_gdpr},
|
||||
index::index_handler,
|
||||
@@ -160,6 +160,7 @@ fn html_routes(
|
||||
)
|
||||
.route("/account", get(show_account_page))
|
||||
.route("/set-api-key", post(set_api_key))
|
||||
.route("/get-ios-shortcut", get(show_ios_shortcut))
|
||||
.route("/delete-account", delete(delete_account))
|
||||
.route(
|
||||
"/signup",
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use axum::{
|
||||
extract::State,
|
||||
extract::{Query, State},
|
||||
http::{StatusCode, Uri},
|
||||
response::{IntoResponse, Redirect},
|
||||
response::{Html, IntoResponse, Redirect},
|
||||
};
|
||||
use axum_htmx::HxRedirect;
|
||||
use axum_session_auth::AuthSession;
|
||||
@@ -96,3 +98,134 @@ pub async fn delete_account(
|
||||
|
||||
Ok((HxRedirect::from(Uri::from_static("/")), StatusCode::OK).into_response())
|
||||
}
|
||||
|
||||
pub async fn show_ios_shortcut(
|
||||
State(state): State<AppState>,
|
||||
auth: AuthSession<User, String, SessionSurrealPool<Any>, Surreal<Any>>,
|
||||
) -> Result<impl IntoResponse, HtmlError> {
|
||||
let user = match &auth.current_user {
|
||||
Some(user) => user,
|
||||
None => return Ok(Redirect::to("/").into_response()),
|
||||
};
|
||||
let base_url = "https://minne.starks.cloud";
|
||||
let shortcut_url = format!(
|
||||
"{}/api/shortcuts/template?key={:?}",
|
||||
base_url,
|
||||
user.api_key.as_ref().unwrap()
|
||||
);
|
||||
let deep_link = format!("shortcuts://import-workflow?url={}", &shortcut_url);
|
||||
|
||||
Ok(Html(format!(
|
||||
r#"
|
||||
<div class="p-4 mt-4 flex flex-col justify-center items-center border rounded-lg bg-base-200">
|
||||
<h3 class="text-lg font-bold mb-2">Install iOS Shortcut</h3>
|
||||
<ol class="list-decimal list-inside space-y-2 mb-4">
|
||||
<li>Open Settings > Shortcuts</li>
|
||||
<li>Enable "Allow Untrusted Shortcuts"</li>
|
||||
<li><a href="{}" class="btn btn-primary">Click here to install shortcut</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
"#,
|
||||
deep_link
|
||||
))
|
||||
.into_response())
|
||||
}
|
||||
|
||||
// pub async fn serve_shortcut_template(
|
||||
// Query(params): Query<HashMap<String, String>>,
|
||||
// ) -> impl IntoResponse {
|
||||
// let api_key = params.get("key").cloned().unwrap_or_default();
|
||||
|
||||
// // Create the shortcut structure as a plist Value
|
||||
// let shortcut = Value::Dictionary(plist::Dictionary::from_iter([
|
||||
// (
|
||||
// "WFWorkflowActions".into(),
|
||||
// Value::Array(vec![
|
||||
// // Text input action
|
||||
// Value::Dictionary(plist::Dictionary::from_iter([
|
||||
// (
|
||||
// "WFWorkflowActionIdentifier".into(),
|
||||
// Value::String("is.workflow.actions.ask".into()),
|
||||
// ),
|
||||
// (
|
||||
// "WFWorkflowActionParameters".into(),
|
||||
// Value::Dictionary(plist::Dictionary::from_iter([
|
||||
// (
|
||||
// "WFAskActionPrompt".into(),
|
||||
// Value::String("Enter content or notes".into()),
|
||||
// ),
|
||||
// ("WFInputType".into(), Value::String("Text".into())),
|
||||
// ])),
|
||||
// ),
|
||||
// ])),
|
||||
// // File picker action
|
||||
// Value::Dictionary(plist::Dictionary::from_iter([
|
||||
// (
|
||||
// "WFWorkflowActionIdentifier".into(),
|
||||
// Value::String("is.workflow.actions.documentpicker".into()),
|
||||
// ),
|
||||
// (
|
||||
// "WFWorkflowActionParameters".into(),
|
||||
// Value::Dictionary(plist::Dictionary::from_iter([(
|
||||
// "WFAllowMultipleSelection".into(),
|
||||
// Value::Boolean(true),
|
||||
// )])),
|
||||
// ),
|
||||
// ])),
|
||||
// // API request action
|
||||
// Value::Dictionary(plist::Dictionary::from_iter([
|
||||
// (
|
||||
// "WFWorkflowActionIdentifier".into(),
|
||||
// Value::String("is.workflow.actions.downloadurl".into()),
|
||||
// ),
|
||||
// (
|
||||
// "WFWorkflowActionParameters".into(),
|
||||
// Value::Dictionary(plist::Dictionary::from_iter([
|
||||
// ("Method".into(), Value::String("POST".into())),
|
||||
// (
|
||||
// "URL".into(),
|
||||
// Value::String("http://your-api-endpoint.com/api/v2/ingress".into()),
|
||||
// ),
|
||||
// (
|
||||
// "Advanced".into(),
|
||||
// Value::Dictionary(plist::Dictionary::from_iter([(
|
||||
// "Headers".into(),
|
||||
// Value::Dictionary(plist::Dictionary::from_iter([(
|
||||
// "X-API-Key".into(),
|
||||
// Value::String(api_key),
|
||||
// )])),
|
||||
// )])),
|
||||
// ),
|
||||
// ])),
|
||||
// ),
|
||||
// ])),
|
||||
// ]),
|
||||
// ),
|
||||
// (
|
||||
// "WFWorkflowName".into(),
|
||||
// Value::String("Share to Your App".into()),
|
||||
// ),
|
||||
// (
|
||||
// "WFWorkflowTypes".into(),
|
||||
// Value::Array(vec![
|
||||
// Value::String("NCWidget".into()),
|
||||
// Value::String("WatchKit".into()),
|
||||
// Value::String("QuickActions".into()),
|
||||
// ]),
|
||||
// ),
|
||||
// ]));
|
||||
|
||||
// // Create a buffer to write the binary plist
|
||||
// let mut buffer = Cursor::new(Vec::new());
|
||||
// plist::to_writer_binary(&mut buffer, &shortcut).unwrap();
|
||||
// // ...
|
||||
|
||||
// Response::builder()
|
||||
// .header("Content-Type", "application/x-ios-workflow")
|
||||
// .header(
|
||||
// "Content-Disposition",
|
||||
// "attachment; filename=\"share_to_app.shortcut\"",
|
||||
// )
|
||||
// .body(buffer.into_inner())
|
||||
// .unwrap()
|
||||
// }
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
{% block api_key_section %}
|
||||
{% if user.api_key %}
|
||||
<input type="text" name="api-key" value="{{ user.api_key }}" class="input input-bordered w-full" disabled />
|
||||
<button hx-get="/get-ios-shortcut" class="btn btn-accent mt-4" hx-swap="outerHTML">Download iOS
|
||||
shortcut</button>
|
||||
{% else %}
|
||||
<button hx-post="/set-api-key" class="btn btn-secondary w-full" hx-swap="outerHTML">
|
||||
Create API-Key
|
||||
|
||||
Reference in New Issue
Block a user