mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-02-18 16:47:48 +01:00
Compare commits
9 Commits
v2025.6.0-
...
v2025.6.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a1751c23e | ||
|
|
17de0678b0 | ||
|
|
20bb89de33 | ||
|
|
8a634b1056 | ||
|
|
57f231ca00 | ||
|
|
cb1c0e4d8c | ||
|
|
2152cf87d7 | ||
|
|
8662b230e7 | ||
|
|
3a8a6484c7 |
@@ -88,9 +88,9 @@ export async function getAuthorizationCode(
|
||||
const code = await new Promise<string>(async (resolve, reject) => {
|
||||
let foundCode = false;
|
||||
const { close } = await ctx.window.openUrl({
|
||||
dataDirKey,
|
||||
url: authorizationUrlStr,
|
||||
label: 'oauth-authorization-url',
|
||||
dataDirKey,
|
||||
async onClose() {
|
||||
if (!foundCode) {
|
||||
reject(new Error('Authorization window closed'));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Context } from '@yaakapp/api';
|
||||
import type { AccessToken, AccessTokenRawResponse } from '../store';
|
||||
import { getToken, storeToken } from '../store';
|
||||
import type { AccessToken, AccessTokenRawResponse} from '../store';
|
||||
import { getDataDirKey , getToken, storeToken } from '../store';
|
||||
import { isTokenExpired } from '../util';
|
||||
|
||||
export async function getImplicit(
|
||||
@@ -60,7 +60,9 @@ export async function getImplicit(
|
||||
const newToken = await new Promise<AccessToken>(async (resolve, reject) => {
|
||||
let foundAccessToken = false;
|
||||
const authorizationUrlStr = authorizationUrl.toString();
|
||||
const dataDirKey = await getDataDirKey(ctx, contextId);
|
||||
const { close } = await ctx.window.openUrl({
|
||||
dataDirKey,
|
||||
url: authorizationUrlStr,
|
||||
label: 'oauth-authorization-url',
|
||||
async onClose() {
|
||||
|
||||
@@ -91,21 +91,21 @@ yaak-ws = { path = "yaak-ws" }
|
||||
[workspace.dependencies]
|
||||
chrono = "0.4.41"
|
||||
hex = "0.4.3"
|
||||
keyring = { version = "3.6.3", features = ["apple-native", "windows-native", "sync-secret-service"] }
|
||||
keyring = "3.6.3"
|
||||
reqwest = "0.12.20"
|
||||
reqwest_cookie_store = "0.8.0"
|
||||
rustls = { version = "0.23.27", default-features = false }
|
||||
rustls-platform-verifier = "0.6.0"
|
||||
serde = "1.0.219"
|
||||
serde_json = "1.0.140"
|
||||
sha2 = "0.10.9"
|
||||
tauri = "2.8.5"
|
||||
tauri-plugin = "2.4.0"
|
||||
tauri-plugin-dialog = "2.4.0"
|
||||
tauri-plugin-shell = "2.3.1"
|
||||
tokio = "1.45.1"
|
||||
thiserror = "2.0.12"
|
||||
tokio = "1.45.1"
|
||||
ts-rs = "11.0.1"
|
||||
reqwest_cookie_store = "0.8.0"
|
||||
rustls = { version = "0.23.27", default-features = false }
|
||||
rustls-platform-verifier = "0.6.0"
|
||||
sha2 = "0.10.9"
|
||||
yaak-common = { path = "yaak-common" }
|
||||
yaak-crypto = { path = "yaak-crypto" }
|
||||
yaak-fonts = { path = "yaak-fonts" }
|
||||
|
||||
@@ -1198,13 +1198,13 @@ async fn cmd_new_child_window(
|
||||
title: &str,
|
||||
inner_size: (f64, f64),
|
||||
) -> YaakResult<()> {
|
||||
window::create_child_window(&parent_window, url, label, title, inner_size);
|
||||
window::create_child_window(&parent_window, url, label, title, inner_size)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn cmd_new_main_window(app_handle: AppHandle, url: &str) -> YaakResult<()> {
|
||||
window::create_main_window(&app_handle, url);
|
||||
window::create_main_window(&app_handle, url)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1304,6 +1304,7 @@ pub fn run() {
|
||||
),
|
||||
color: Some(Color::Danger),
|
||||
icon: None,
|
||||
timeout: None,
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
@@ -7,16 +7,16 @@ use crate::{
|
||||
};
|
||||
use chrono::Utc;
|
||||
use cookie::Cookie;
|
||||
use log::warn;
|
||||
use log::{error, warn};
|
||||
use tauri::{AppHandle, Emitter, Manager, Runtime, State};
|
||||
use tauri_plugin_clipboard_manager::ClipboardExt;
|
||||
use yaak_models::models::{HttpResponse, Plugin};
|
||||
use yaak_models::query_manager::QueryManagerExt;
|
||||
use yaak_models::util::UpdateSource;
|
||||
use yaak_plugins::events::{
|
||||
Color, DeleteKeyValueResponse, EmptyPayload, FindHttpResponsesResponse, GetCookieValueResponse,
|
||||
GetHttpRequestByIdResponse, GetKeyValueResponse, Icon, InternalEvent, InternalEventPayload,
|
||||
ListCookieNamesResponse, PluginWindowContext, RenderGrpcRequestResponse,
|
||||
Color, DeleteKeyValueResponse, EmptyPayload, ErrorResponse, FindHttpResponsesResponse,
|
||||
GetCookieValueResponse, GetHttpRequestByIdResponse, GetKeyValueResponse, Icon, InternalEvent,
|
||||
InternalEventPayload, ListCookieNamesResponse, PluginWindowContext, RenderGrpcRequestResponse,
|
||||
RenderHttpRequestResponse, SendHttpRequestResponse, SetKeyValueResponse, ShowToastRequest,
|
||||
TemplateRenderResponse, WindowNavigateEvent,
|
||||
};
|
||||
@@ -124,6 +124,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
Some(InternalEventPayload::TemplateRenderResponse(TemplateRenderResponse { data }))
|
||||
}
|
||||
InternalEventPayload::ErrorResponse(resp) => {
|
||||
error!("Plugin error: {}: {:?}", resp.error, resp);
|
||||
let toast_event = plugin_handle.build_event_to_send(
|
||||
&window_context,
|
||||
&InternalEventPayload::ShowToastRequest(ShowToastRequest {
|
||||
@@ -133,6 +134,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
resp.error
|
||||
),
|
||||
color: Some(Color::Danger),
|
||||
timeout: None,
|
||||
..Default::default()
|
||||
}),
|
||||
None,
|
||||
@@ -218,20 +220,29 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
}))
|
||||
}
|
||||
InternalEventPayload::OpenWindowRequest(req) => {
|
||||
let label = req.label;
|
||||
let (navigation_tx, mut navigation_rx) = tokio::sync::mpsc::channel(128);
|
||||
let (close_tx, mut close_rx) = tokio::sync::mpsc::channel(128);
|
||||
let win_config = CreateWindowConfig {
|
||||
url: &req.url,
|
||||
label: &label.clone(),
|
||||
title: &req.title.unwrap_or_default(),
|
||||
label: &req.label,
|
||||
title: &req.title.clone().unwrap_or_default(),
|
||||
navigation_tx: Some(navigation_tx),
|
||||
close_tx: Some(close_tx),
|
||||
inner_size: req.size.map(|s| (s.width, s.height)),
|
||||
data_dir_key: req.data_dir_key,
|
||||
inner_size: req.size.clone().map(|s| (s.width, s.height)),
|
||||
data_dir_key: req.data_dir_key.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
create_window(app_handle, win_config);
|
||||
if let Err(e) = create_window(app_handle, win_config) {
|
||||
let error_event = plugin_handle.build_event_to_send(
|
||||
&window_context,
|
||||
&InternalEventPayload::ErrorResponse(ErrorResponse {
|
||||
error: format!("Failed to create window: {:?}", e),
|
||||
}),
|
||||
None,
|
||||
);
|
||||
Box::pin(handle_plugin_event(app_handle, &error_event, plugin_handle)).await;
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
let event_id = event.id.clone();
|
||||
|
||||
@@ -47,6 +47,7 @@ pub(crate) async fn handle_deep_link<R: Runtime>(
|
||||
message: format!("Installed {name}@{}", pv.version),
|
||||
color: Some(Color::Success),
|
||||
icon: None,
|
||||
timeout: Some(5000),
|
||||
},
|
||||
)?;
|
||||
}
|
||||
@@ -90,6 +91,7 @@ pub(crate) async fn handle_deep_link<R: Runtime>(
|
||||
message: "Failed to import data".to_string(),
|
||||
color: Some(Color::Danger),
|
||||
icon: None,
|
||||
timeout: None,
|
||||
},
|
||||
)?;
|
||||
return Ok(());
|
||||
@@ -103,6 +105,7 @@ pub(crate) async fn handle_deep_link<R: Runtime>(
|
||||
message: format!("Imported data for {} workspaces", results.workspaces.len()),
|
||||
color: Some(Color::Success),
|
||||
icon: None,
|
||||
timeout: Some(5000),
|
||||
},
|
||||
)?;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ use tauri::{
|
||||
};
|
||||
use tauri_plugin_opener::OpenerExt;
|
||||
use tokio::sync::mpsc;
|
||||
use crate::error::Result;
|
||||
|
||||
const DEFAULT_WINDOW_WIDTH: f64 = 1100.0;
|
||||
const DEFAULT_WINDOW_HEIGHT: f64 = 600.0;
|
||||
@@ -32,9 +33,9 @@ pub(crate) struct CreateWindowConfig<'s> {
|
||||
pub(crate) fn create_window<R: Runtime>(
|
||||
handle: &AppHandle<R>,
|
||||
config: CreateWindowConfig,
|
||||
) -> WebviewWindow<R> {
|
||||
) -> Result<WebviewWindow<R>> {
|
||||
#[allow(unused_variables)]
|
||||
let menu = app_menu(handle).unwrap();
|
||||
let menu = app_menu(handle)?;
|
||||
|
||||
// This causes the window to not be clickable (in AppImage), so disable on Linux
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
@@ -55,12 +56,13 @@ pub(crate) fn create_window<R: Runtime>(
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
use std::fs;
|
||||
let dir = handle.path().temp_dir().unwrap().join("yaak_sessions").join(key);
|
||||
fs::create_dir_all(dir.clone()).unwrap();
|
||||
let safe_key = format!("{:x}", md5::compute(key.as_bytes()));
|
||||
let dir = handle.path().app_data_dir()?.join("window-sessions").join(safe_key);
|
||||
fs::create_dir_all(&dir)?;
|
||||
win_builder = win_builder.data_directory(dir);
|
||||
}
|
||||
|
||||
// macOS doesn't support data dir so must use this fn instead
|
||||
// macOS doesn't support `data_directory()` so must use this fn instead
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let hash = md5::compute(key.as_bytes());
|
||||
@@ -108,11 +110,11 @@ pub(crate) fn create_window<R: Runtime>(
|
||||
|
||||
if let Some(w) = handle.webview_windows().get(config.label) {
|
||||
info!("Webview with label {} already exists. Focusing existing", config.label);
|
||||
w.set_focus().unwrap();
|
||||
return w.to_owned();
|
||||
w.set_focus()?;
|
||||
return Ok(w.to_owned());
|
||||
}
|
||||
|
||||
let win = win_builder.build().unwrap();
|
||||
let win = win_builder.build()?;
|
||||
|
||||
if let Some(tx) = config.close_tx {
|
||||
win.on_window_event(move |event| match event {
|
||||
@@ -174,10 +176,10 @@ pub(crate) fn create_window<R: Runtime>(
|
||||
}
|
||||
});
|
||||
|
||||
win
|
||||
Ok(win)
|
||||
}
|
||||
|
||||
pub(crate) fn create_main_window(handle: &AppHandle, url: &str) -> WebviewWindow {
|
||||
pub(crate) fn create_main_window(handle: &AppHandle, url: &str) -> Result<WebviewWindow> {
|
||||
let mut counter = 0;
|
||||
let label = loop {
|
||||
let label = format!("{MAIN_WINDOW_PREFIX}{counter}");
|
||||
@@ -211,7 +213,7 @@ pub(crate) fn create_child_window(
|
||||
label: &str,
|
||||
title: &str,
|
||||
inner_size: (f64, f64),
|
||||
) -> WebviewWindow {
|
||||
) -> Result<WebviewWindow> {
|
||||
let app_handle = parent_window.app_handle();
|
||||
let label = format!("{OTHER_WINDOW_PREFIX}_{label}");
|
||||
let scale_factor = parent_window.scale_factor().unwrap();
|
||||
@@ -235,7 +237,7 @@ pub(crate) fn create_child_window(
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let child_window = create_window(&app_handle, config);
|
||||
let child_window = create_window(&app_handle, config)?;
|
||||
|
||||
// NOTE: These listeners will remain active even when the windows close. Unfortunately,
|
||||
// there's no way to unlisten to events for now, so we just have to be defensive.
|
||||
@@ -272,5 +274,5 @@ pub(crate) fn create_child_window(
|
||||
});
|
||||
}
|
||||
|
||||
child_window
|
||||
Ok(child_window)
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"createUpdaterArtifacts": "v1Compatible"
|
||||
"createUpdaterArtifacts": "v1Compatible",
|
||||
"windows": {
|
||||
"signCommand": "trusted-signing-cli -e https://eus.codesigning.azure.net/ -a Yaak -c yaakapp %1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ publish = false
|
||||
base32 = "0.5.1" # For encoding human-readable key
|
||||
base64 = "0.22.1" # For encoding in the database
|
||||
chacha20poly1305 = "0.10.1"
|
||||
keyring = { workspace = true }
|
||||
keyring = { workspace = true, features = ["apple-native", "windows-native", "sync-secret-service"] }
|
||||
log = "0.4.26"
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
tauri = { workspace = true }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type Environment = { model: "environment", id: string, workspaceId: string, createdAt: string, updatedAt: string, name: string, public: boolean, variables: Array<EnvironmentVariable>, color: string | null, parentModel: string, parentId: string | null, };
|
||||
export type Environment = { model: "environment", id: string, workspaceId: string, createdAt: string, updatedAt: string, name: string, public: boolean, parentModel: string, parentId: string | null, variables: Array<EnvironmentVariable>, color: string | null, };
|
||||
|
||||
export type EnvironmentVariable = { enabled?: boolean, name: string, value: string, id?: string, };
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ export type EditorKeymap = "default" | "vim" | "vscode" | "emacs";
|
||||
|
||||
export type EncryptedKey = { encryptedKey: string, };
|
||||
|
||||
export type Environment = { model: "environment", id: string, workspaceId: string, createdAt: string, updatedAt: string, name: string, public: boolean, variables: Array<EnvironmentVariable>, color: string | null, parentModel: string, parentId: string | null, };
|
||||
export type Environment = { model: "environment", id: string, workspaceId: string, createdAt: string, updatedAt: string, name: string, public: boolean, parentModel: string, parentId: string | null, variables: Array<EnvironmentVariable>, color: string | null, };
|
||||
|
||||
export type EnvironmentVariable = { enabled?: boolean, name: string, value: string, id?: string, };
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { Environment, Folder, GrpcRequest, HttpRequest, WebsocketRequest, Workspace } from "./gen_models";
|
||||
import type { Environment, Folder, GrpcRequest, HttpRequest, WebsocketRequest, Workspace } from "./gen_models.js";
|
||||
|
||||
export type BatchUpsertResult = { workspaces: Array<Workspace>, environments: Array<Environment>, folders: Array<Folder>, httpRequests: Array<HttpRequest>, grpcRequests: Array<GrpcRequest>, websocketRequests: Array<WebsocketRequest>, };
|
||||
|
||||
@@ -541,10 +541,15 @@ pub struct Environment {
|
||||
|
||||
pub name: String,
|
||||
pub public: bool,
|
||||
pub variables: Vec<EnvironmentVariable>,
|
||||
pub color: Option<String>,
|
||||
#[deprecated(
|
||||
note = "parent_model is used instead. This field will be removed when schema field is added for sync/export."
|
||||
)]
|
||||
#[ts(skip)]
|
||||
pub base: bool,
|
||||
pub parent_model: String,
|
||||
pub parent_id: Option<String>,
|
||||
pub variables: Vec<EnvironmentVariable>,
|
||||
pub color: Option<String>,
|
||||
}
|
||||
|
||||
impl UpsertModelInfo for Environment {
|
||||
@@ -603,6 +608,8 @@ impl UpsertModelInfo for Environment {
|
||||
Self: Sized,
|
||||
{
|
||||
let variables: String = row.get("variables")?;
|
||||
let parent_model = row.get("parent_model")?;
|
||||
let base = parent_model == "workspace";
|
||||
Ok(Self {
|
||||
id: row.get("id")?,
|
||||
model: row.get("model")?,
|
||||
@@ -610,11 +617,16 @@ impl UpsertModelInfo for Environment {
|
||||
created_at: row.get("created_at")?,
|
||||
updated_at: row.get("updated_at")?,
|
||||
parent_id: row.get("parent_id")?,
|
||||
parent_model: row.get("parent_model")?,
|
||||
parent_model,
|
||||
color: row.get("color")?,
|
||||
name: row.get("name")?,
|
||||
public: row.get("public")?,
|
||||
variables: serde_json::from_str(variables.as_str()).unwrap_or_default(),
|
||||
|
||||
// Deprecated field, but we need to keep it around for a couple of versions
|
||||
// for compatibility because sync/export don't have a schema field
|
||||
#[allow(deprecated)]
|
||||
base,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,11 @@ publish = false
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.22.1"
|
||||
chrono = { workspace = true }
|
||||
dunce = "1.0.4"
|
||||
futures-util = "0.3.30"
|
||||
hex = { workspace = true }
|
||||
keyring = { workspace = true, features = ["apple-native", "windows-native", "sync-secret-service"] }
|
||||
log = "0.4.21"
|
||||
md5 = "0.7.0"
|
||||
path-slash = "0.2.1"
|
||||
@@ -17,21 +20,18 @@ regex = "1.10.6"
|
||||
reqwest = { workspace = true, features = ["json"] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
sha2 = { workspace = true }
|
||||
tauri = { workspace = true }
|
||||
tauri-plugin-shell = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tokio = { workspace = true, features = ["macros", "rt-multi-thread", "process"] }
|
||||
tokio-tungstenite = "0.26.1"
|
||||
ts-rs = { workspace = true, features = ["import-esm"] }
|
||||
sha2 = { workspace = true }
|
||||
yaak-common = { workspace = true }
|
||||
yaak-crypto = { workspace = true }
|
||||
yaak-models = { workspace = true }
|
||||
yaak-templates = { workspace = true }
|
||||
zip-extract = "0.4.0"
|
||||
chrono = { workspace = true }
|
||||
hex = { workspace = true }
|
||||
keyring = { workspace = true }
|
||||
|
||||
[build-dependencies]
|
||||
tauri-plugin = { workspace = true, features = ["build"] }
|
||||
|
||||
@@ -437,7 +437,7 @@ export type SetKeyValueRequest = { key: string, value: string, };
|
||||
|
||||
export type SetKeyValueResponse = {};
|
||||
|
||||
export type ShowToastRequest = { message: string, color?: Color, icon?: Icon, };
|
||||
export type ShowToastRequest = { message: string, color?: Color, icon?: Icon, timeout?: number, };
|
||||
|
||||
export type TemplateFunction = { name: string, description?: string,
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type Environment = { model: "environment", id: string, workspaceId: string, createdAt: string, updatedAt: string, name: string, public: boolean, variables: Array<EnvironmentVariable>, color: string | null, parentModel: string, parentId: string | null, };
|
||||
export type Environment = { model: "environment", id: string, workspaceId: string, createdAt: string, updatedAt: string, name: string, public: boolean, parentModel: string, parentId: string | null, variables: Array<EnvironmentVariable>, color: string | null, };
|
||||
|
||||
export type EnvironmentVariable = { enabled?: boolean, name: string, value: string, id?: string, };
|
||||
|
||||
|
||||
@@ -494,6 +494,9 @@ pub struct ShowToastRequest {
|
||||
|
||||
#[ts(optional)]
|
||||
pub icon: Option<Icon>,
|
||||
|
||||
#[ts(optional)]
|
||||
pub timeout: Option<i32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type Environment = { model: "environment", id: string, workspaceId: string, createdAt: string, updatedAt: string, name: string, public: boolean, variables: Array<EnvironmentVariable>, color: string | null, parentModel: string, parentId: string | null, };
|
||||
export type Environment = { model: "environment", id: string, workspaceId: string, createdAt: string, updatedAt: string, name: string, public: boolean, parentModel: string, parentId: string | null, variables: Array<EnvironmentVariable>, color: string | null, };
|
||||
|
||||
export type EnvironmentVariable = { enabled?: boolean, name: string, value: string, id?: string, };
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ const details: Record<
|
||||
commercial_use: null,
|
||||
invalid_license: { label: 'License Error', color: 'danger' },
|
||||
personal_use: { label: 'Personal Use', color: 'notice' },
|
||||
trialing: { label: 'Personal Use', color: 'info' },
|
||||
trialing: { label: 'Trialing', color: 'info' },
|
||||
};
|
||||
|
||||
export function LicenseBadge() {
|
||||
@@ -46,11 +46,6 @@ function LicenseBadgeCmp() {
|
||||
return null;
|
||||
}
|
||||
|
||||
// User is trialing but has already seen the message, so hide badge
|
||||
if (check.data.type === 'trialing') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const detail = details[check.data.type];
|
||||
if (detail == null) {
|
||||
return null;
|
||||
@@ -59,9 +54,7 @@ function LicenseBadgeCmp() {
|
||||
return (
|
||||
<BadgeButton
|
||||
color={detail.color}
|
||||
onClick={async () => {
|
||||
openSettings.mutate('license');
|
||||
}}
|
||||
onClick={() => openSettings.mutate('license')}
|
||||
>
|
||||
{detail.label}
|
||||
</BadgeButton>
|
||||
|
||||
@@ -35,17 +35,17 @@ function SettingsLicenseCmp() {
|
||||
{check.data?.type === 'commercial_use' ? (
|
||||
<Banner color="success">Your license is active 🥳</Banner>
|
||||
) : check.data?.type == 'trialing' ? (
|
||||
<Banner color="success" className="flex flex-col gap-3 max-w-lg">
|
||||
<p className="select-text">
|
||||
<Banner color="info" className="flex flex-col gap-3 max-w-lg">
|
||||
<p>
|
||||
<strong>
|
||||
{pluralizeCount('day', differenceInDays(check.data.end, new Date()))} remaining
|
||||
</strong>{' '}
|
||||
on trial
|
||||
on your commercial-use trial
|
||||
</p>
|
||||
</Banner>
|
||||
) : check.data?.type == 'personal_use' ? (
|
||||
<Banner color="success" className="flex flex-col gap-3 max-w-lg">
|
||||
<p>Your free trial has ended</p>
|
||||
<Banner color="notice" className="flex flex-col gap-3 max-w-lg">
|
||||
<p>You are able to use Yaak for personal use only</p>
|
||||
</Banner>
|
||||
) : null}
|
||||
|
||||
@@ -62,7 +62,7 @@ function SettingsLicenseCmp() {
|
||||
<p>
|
||||
<Link
|
||||
noUnderline
|
||||
href="https://yaak.app/pricing?s=learn"
|
||||
href={`https://yaak.app/pricing?s=learn&t=${check.data?.type ?? ''}`}
|
||||
className="text-sm text-notice opacity-80 hover:opacity-100"
|
||||
>
|
||||
Learn More
|
||||
@@ -90,7 +90,7 @@ function SettingsLicenseCmp() {
|
||||
<Button
|
||||
color="secondary"
|
||||
size="sm"
|
||||
onClick={() => openUrl('https://yaak.app/dashboard?s=support')}
|
||||
onClick={() => openUrl('https://yaak.app/dashboard?s=support&ref=app.yaak.desktop')}
|
||||
rightSlot={<Icon icon="external_link" />}
|
||||
>
|
||||
Direct Support
|
||||
@@ -98,16 +98,20 @@ function SettingsLicenseCmp() {
|
||||
</HStack>
|
||||
) : (
|
||||
<HStack space={2}>
|
||||
<Button color="primary" size="sm" onClick={toggleActivateFormVisible}>
|
||||
Activate
|
||||
<Button variant="border" color="secondary" size="sm" onClick={toggleActivateFormVisible}>
|
||||
Activate License
|
||||
</Button>
|
||||
<Button
|
||||
color="secondary"
|
||||
size="sm"
|
||||
onClick={() => openUrl('https://yaak.app/pricing?s=purchase&ref=app.yaak.desktop')}
|
||||
color="primary"
|
||||
onClick={() =>
|
||||
openUrl(
|
||||
`https://yaak.app/pricing?s=purchase&ref=app.yaak.desktop&t=${check.data?.type ?? ''}`,
|
||||
)
|
||||
}
|
||||
rightSlot={<Icon icon="external_link" />}
|
||||
>
|
||||
Purchase
|
||||
Purchase License
|
||||
</Button>
|
||||
</HStack>
|
||||
)}
|
||||
|
||||
@@ -196,7 +196,7 @@ function InitializedTemplateFunctionDialog({
|
||||
</HStack>
|
||||
<InlineCode
|
||||
className={classNames(
|
||||
'whitespace-pre-wrap select-text cursor-text max-h-[10rem] overflow-y-auto hide-scrollbars',
|
||||
'whitespace-pre-wrap !select-text cursor-text max-h-[10rem] overflow-y-auto hide-scrollbars',
|
||||
tooLarge && 'italic text-danger',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
import classNames from 'classnames';
|
||||
import type { ButtonProps } from './Button';
|
||||
import { Button } from './Button';
|
||||
|
||||
export function BadgeButton(props: ButtonProps) {
|
||||
return <Button size="2xs" variant="border" className="!rounded-full mx-1" {...props} />;
|
||||
export function BadgeButton({ className, ...props }: ButtonProps) {
|
||||
return (
|
||||
<Button
|
||||
size="2xs"
|
||||
variant="border"
|
||||
className={classNames(className, '!rounded-full mx-1 !px-3')}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user