Tauri (local working) (#128)

* chore(nix): add `cargo-tauri`

* chore(rust): add rustfmt config

* feat: add tauri app

* fix(config): tauri and web config nextjs

* fix: default value

* fix: force graph

* fix: undefined me

* fix: undefined me in page detail

* fix: remove title from search component

* fix: package version

* chore: next config

* feat: random btn for go to auth

* fix the config

* feat: tauri

---------

Co-authored-by: Alice Carroll <git@alice-carroll.pet>
Co-authored-by: Aslam H <iupin5212@gmail.com>
This commit is contained in:
Nikita
2024-09-03 18:37:10 +03:00
committed by GitHub
parent 91f96fe65a
commit 8168af811d
46 changed files with 8990 additions and 34 deletions

4
.gitignore vendored
View File

@@ -14,4 +14,6 @@ private
past-*
output
dist
target
# rust
/target/

22
.rustfmt.toml Normal file
View File

@@ -0,0 +1,22 @@
#:schema https://json.schemastore.org/rustfmt.json
edition = "2021"
format_code_in_doc_comments = true
format_macro_bodies = true
format_macro_matchers = true
format_strings = true
group_imports = "StdExternalCrate"
hex_literal_case = "Upper"
imports_granularity = "Crate"
imports_layout = "HorizontalVertical"
match_arm_blocks = true
match_block_trailing_comma = true
reorder_impl_items = true
unstable_features = true
use_field_init_shorthand = true
use_small_heuristics = "Max"
use_try_shorthand = true
wrap_comments = true
hard_tabs = true
max_width = 120
newline_style = "Unix"

6
.taplo.toml Normal file
View File

@@ -0,0 +1,6 @@
[formatting]
column_width = 120
crlf = false
indent_string = "\t"
reorder_keys = true
trailing_newline = true

4365
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

11
Cargo.toml Normal file
View File

@@ -0,0 +1,11 @@
[workspace]
members = ["app"]
resolver = "2"
[workspace.package]
authors = ["Alice Carroll <learn-anything@alice-carroll.pet>"]
edition = "2021"
license-file = "license"
repository = "https://github.com/learn-anything/learn-anything.xyz"
rust-version = "1.80"
version = "0.1.0"

3
app/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
# Generated by Cargo
# will have compiled files and executables
/gen/schemas

4365
app/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

20
app/Cargo.toml Normal file
View File

@@ -0,0 +1,20 @@
[package]
authors.workspace = true
edition.workspace = true
license-file.workspace = true
name = "learn-anything"
repository.workspace = true
rust-version.workspace = true
version.workspace = true
[lib]
crate-type = ["staticlib", "cdylib", "lib"]
name = "app_lib"
[build-dependencies]
tauri-build = { version = "2.0.0-rc.6", features = [] }
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tauri = { version = "2.0.0-rc.6", features = [] }

3
app/build.rs Normal file
View File

@@ -0,0 +1,3 @@
fn main() {
tauri_build::build()
}

View File

@@ -0,0 +1,11 @@
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "enables the default permissions",
"windows": [
"main"
],
"permissions": [
"core:default"
]
}

BIN
app/icons/128x128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
app/icons/128x128@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
app/icons/32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

BIN
app/icons/StoreLogo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
app/icons/icon.icns Normal file

Binary file not shown.

BIN
app/icons/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
app/icons/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

4
app/src/lib.rs Normal file
View File

@@ -0,0 +1,4 @@
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default().run(tauri::generate_context!()).expect("error while running tauri application");
}

6
app/src/main.rs Normal file
View File

@@ -0,0 +1,6 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() {
app_lib::run();
}

31
app/tauri.conf.json Normal file
View File

@@ -0,0 +1,31 @@
{
"productName": "learn-anything",
"version": "0.1.0",
"identifier": "xyz.learn-anything",
"build": {
"frontendDist": "../out",
"devUrl": "http://localhost:3000",
"beforeDevCommand": "bun dev",
"beforeBuildCommand": "bun build"
},
"app": {
"windows": [
{
"title": "Learn Anything",
"width": 800,
"height": 600,
"resizable": true,
"fullscreen": false,
"url": "http://localhost:3000"
}
],
"security": {
"csp": null
}
},
"bundle": {
"active": true,
"targets": "all",
"icon": ["icons/32x32.png", "icons/128x128.png", "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico"]
}
}

BIN
bun.lockb

Binary file not shown.

8
flake.lock generated
View File

@@ -20,16 +20,16 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1724395761,
"narHash": "sha256-zRkDV/nbrnp3Y8oCADf5ETl1sDrdmAW6/bBVJ8EbIdQ=",
"lastModified": 1725041072,
"narHash": "sha256-VQz/S5SYgmERo8orFuBJSP/2dE08RMXu4YaVaO9jowo=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "ae815cee91b417be55d43781eb4b73ae1ecc396c",
"rev": "d8c78f272ca287089e989dbb3c43594b0929d73d",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"ref": "staging",
"repo": "nixpkgs",
"type": "github"
}

View File

@@ -1,6 +1,7 @@
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
# TODO: switch to nixpkgs-unstable when 69f3b4defe91949a97ca751ada931525d391e0fc is there
nixpkgs.url = "github:nixos/nixpkgs/staging";
flake-parts.url = "github:hercules-ci/flake-parts";
};
outputs =
@@ -8,13 +9,21 @@
flake-parts.lib.mkFlake { inherit inputs; } {
systems = nixpkgs.lib.platforms.all;
perSystem =
{ pkgs, ... }:
{ pkgs, lib, ... }:
let
cargo-tauri = pkgs.callPackage ./nix/cargo-tauri.nix { };
in
{
devShells.default = pkgs.mkShell {
packages = [
pkgs.bun
pkgs.nodejs
];
packages =
[
pkgs.bun
pkgs.nodejs
cargo-tauri
]
++ lib.optionals pkgs.stdenv.isDarwin (
[ pkgs.libiconv ] ++ (with pkgs.darwin.apple_sdk.frameworks; [ WebKit ])
);
};
# TODO: Package LA using Nix
};

67
nix/cargo-tauri.nix Normal file
View File

@@ -0,0 +1,67 @@
# TODO: use upstream cargo-tauri when it is updated to v2 in nixpkgs
# copied from nixpkgs to change the version and hashes
{
lib,
stdenv,
rustPlatform,
fetchFromGitHub,
openssl,
pkg-config,
glibc,
libsoup,
cairo,
gtk3,
webkitgtk,
darwin,
}:
let
inherit (darwin.apple_sdk.frameworks) CoreServices Security SystemConfiguration;
in
rustPlatform.buildRustPackage rec {
pname = "tauri";
version = "2.0.0-rc.7";
src = fetchFromGitHub {
owner = "tauri-apps";
repo = pname;
rev = "tauri-cli-v${version}";
hash = "sha256-y8Y9En1r1HU9sZcYHFhB+botVQBZfzqoDrlgp98ltrY=";
};
# Manually specify the sourceRoot since this crate depends on other crates in the workspace. Relevant info at
# https://discourse.nixos.org/t/difficulty-using-buildrustpackage-with-a-src-containing-multiple-cargo-workspaces/10202
sourceRoot = "${src.name}/tooling/cli";
cargoHash = "sha256-u1JcLuP9KFCIb7Wkk3u/hoV/bBarEvFfqpGXVyXSvpo=";
buildInputs =
[ openssl ]
++ lib.optionals stdenv.isLinux [
glibc
libsoup
cairo
gtk3
webkitgtk
]
++ lib.optionals stdenv.isDarwin [
CoreServices
Security
SystemConfiguration
];
nativeBuildInputs = [ pkg-config ];
meta = with lib; {
description = "Build smaller, faster, and more secure desktop applications with a web frontend";
mainProgram = "cargo-tauri";
homepage = "https://tauri.app/";
license = with licenses; [
asl20 # or
mit
];
maintainers = with maintainers; [
dit7ya
happysalada
];
};
}

View File

@@ -5,13 +5,15 @@
"web": "cd web && bun dev",
"web:build": "bun run --filter '*' build",
"cli": "bun run --watch cli/run.ts",
"seed": "bun --watch cli/seed.ts"
"seed": "bun --watch cli/seed.ts",
"tauri": "tauri"
},
"workspaces": [
"web"
],
"dependencies": {
"jazz-nodejs": "0.7.35-unique.2",
"@tauri-apps/cli": "^2.0.0-rc.6",
"jazz-nodejs": "^0.7.34",
"react-icons": "^5.3.0"
},
"devDependencies": {

View File

@@ -0,0 +1,5 @@
import TauriRoute from "@/components/routes/tauri/TauriRoute"
export default function TauriPage() {
return <TauriRoute />
}

View File

@@ -3,7 +3,13 @@
*/
import { NextRequest } from "next/server"
import axios from "axios"
import { DEFAULT_VALUES, GET } from "./route"
import { GET } from "./route"
const DEFAULT_VALUES = {
TITLE: "",
DESCRIPTION: "",
FAVICON: null
}
jest.mock("axios")
const mockedAxios = axios as jest.Mocked<typeof axios>

View File

@@ -11,7 +11,7 @@ interface Metadata {
url: string
}
export const DEFAULT_VALUES = {
const DEFAULT_VALUES = {
TITLE: "",
DESCRIPTION: "",
FAVICON: null

View File

@@ -90,6 +90,9 @@ export const ProfileSection: React.FC = () => {
<DropdownMenuItem>
<MenuItem icon="LogOut" text="Log out" onClick={signOut} onClose={closeMenu} />
</DropdownMenuItem>
<DropdownMenuItem>
<MenuItem icon="CircleUser" text="Tauri" href="/tauri" onClose={closeMenu} />
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>

View File

@@ -4,9 +4,13 @@ import type * as force_graph from "./force-graph-client"
import { useCoState } from "@/lib/providers/jazz-provider"
import { PublicGlobalGroup } from "@/lib/schema/master/public-group"
import { ID } from "jazz-tools"
import dynamic from "next/dynamic"
import { Button } from "../ui/button"
import Link from "next/link"
let graph_data_promise = import("./graph-data.json").then(a => a.default)
let ForceGraphClient = react.lazy(() => import("./force-graph-client-lazy"))
// let ForceGraphClient = react.lazy(() => import("./force-graph-client-lazy"))
const ForceGraphClient = dynamic(() => import("./force-graph-client-lazy"), { ssr: false })
export function PublicHomeRoute() {
let raw_graph_data = react.use(graph_data_promise)
@@ -66,6 +70,7 @@ export function PublicHomeRoute() {
/>
<div className="absolute left-0 top-0 z-20 p-4">
<h2 className="text-xl font-bold text-black dark:text-white">Learn Anything</h2>
<Link href={"/1password"}>Random Topic</Link>
</div>
<div className="absolute left-1/2 top-1/2 z-10 w-[60%] -translate-x-1/2 -translate-y-1/2 transform">
<div className="flex flex-col items-center justify-center gap-6">

View File

@@ -204,20 +204,20 @@ const drawGraph = (canvas: fg.canvas.CanvasState, color_map: ColorMap): void =>
ctx.textAlign = "center"
ctx.textBaseline = "middle"
const max_size = Math.max(canvas.ctx.canvas.width, canvas.ctx.canvas.height)
for (const node of graph.nodes) {
const { x, y } = node.position
const opacity = 0.6 + ((node.mass - 1) / 50) * 4
ctx.font = `${
canvas.max_size / 200 + (((node.mass - 1) / 5) * (canvas.max_size / 100)) / canvas.scale
}px sans-serif`
ctx.font = `${max_size / 200 + (((node.mass - 1) / 5) * (max_size / 100)) / canvas.scale}px sans-serif`
ctx.fillStyle =
node.anchor || canvas.hovered_node === node
? `rgba(129, 140, 248, ${opacity})`
: `hsl(${color_map[node.key as string]} / ${opacity})`
ctx.fillText(node.label, (x / graph.grid.size) * canvas.max_size, (y / graph.grid.size) * canvas.max_size)
ctx.fillText(node.label, (x / graph.grid.size) * max_size, (y / graph.grid.size) * max_size)
}
}
@@ -240,7 +240,7 @@ export const createForceGraph = (props: ForceGraphProps): react.JSX.Element => {
let [nodes, edges] = generateNodesFromRawData(props.raw_nodes)
let color_map = generateColorMap(nodes)
let bump_end = anim.bump(0)
let graph = fg.graph.makeGraph(graph_options, nodes.slice(), edges.slice())
/*
@@ -272,7 +272,7 @@ export const createForceGraph = (props: ForceGraphProps): react.JSX.Element => {
let window_size = ws.useWindowSize()
let alpha = 0 // 0 - 1
let bump_end = anim.bump(0)
let frame_iter_limit = anim.frameIterationsLimit()
let loop = anim.animationLoop(time => {

View File

@@ -135,7 +135,7 @@ export const LinkForm: React.FC<LinkFormProps> = ({
}
const onSubmit = (values: LinkFormValues) => {
if (isFetching) return
if (isFetching || !me) return
try {
const personalLinks = me.root?.personalLinks?.toJSON() || []

View File

@@ -82,7 +82,7 @@ export const DetailPageForm = ({ page }: { page: PersonalPage }) => {
// if (newTitle === page.title) return
console.log("Updating page title")
const personalPages = me.root?.personalPages?.toJSON() || []
const personalPages = me?.root?.personalPages?.toJSON() || []
const slug = generateUniqueSlug(personalPages, page.slug || "")
const trimmedTitle = editor.getText().trim()

View File

@@ -3,7 +3,7 @@ import { Input } from "@/components/ui/input"
export const SearchHeader = () => {
return (
<ContentHeader title="Search">
<ContentHeader>
<Input placeholder="Search something..." />
</ContentHeader>
)

View File

@@ -0,0 +1,11 @@
"use client"
import { useAccount } from "@/lib/providers/jazz-provider"
export default function TauriRoute() {
const { me } = useAccount()
console.log({ pages: me?.root?.personalPages?.toJSON() })
return <div>{JSON.stringify(me?.root?.personalPages)}</div>
}

View File

@@ -5,7 +5,6 @@ const isProd = process.env.NODE_ENV === "production"
const internalHost = process.env.TAURI_DEV_HOST || "localhost"
const isIgnoreBuild = process.env.IGNORE_BUILD_ERRORS === "true"
console.log(isIgnoreBuild)
const ignoreBuild = {
typescript: {
ignoreBuildErrors: true
@@ -27,7 +26,7 @@ const commonConfig = {
const tauriConfig = {
...commonConfig,
output: "export",
// output: "export",
images: {
...commonConfig.images,
unoptimized: true

View File

@@ -9,7 +9,7 @@
"test": "jest"
},
"dependencies": {
"@clerk/nextjs": "^5.3.7",
"@clerk/nextjs": "^5.4.0",
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/sortable": "^8.0.0",
"@hookform/resolvers": "^3.9.0",
@@ -60,13 +60,13 @@
"@tiptap/pm": "^2.6.6",
"@tiptap/react": "^2.6.6",
"@tiptap/suggestion": "^2.6.6",
"axios": "^1.7.5",
"axios": "^1.7.7",
"cheerio": "1.0.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
"date-fns": "^3.6.0",
"framer-motion": "^11.3.31",
"framer-motion": "^11.4.0",
"jazz-react": "0.7.35-unique.2",
"jazz-react-auth-clerk": "0.7.33-new-auth.1",
"jazz-tools": "0.7.35-unique.2",
@@ -75,9 +75,9 @@
"lucide-react": "^0.429.0",
"next": "14.2.5",
"next-themes": "^0.3.0",
"nuqs": "^1.17.8",
"nuqs": "^1.19.0",
"react": "^18.3.1",
"react-day-picker": "^9.0.8",
"react-day-picker": "^8.10.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.53.0",
"react-textarea-autosize": "^8.5.3",
@@ -95,14 +95,14 @@
"@testing-library/jest-dom": "^6.5.0",
"@testing-library/react": "^16.0.1",
"@types/jest": "^29.5.12",
"@types/node": "^22.5.1",
"@types/node": "^22.5.2",
"@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0",
"eslint": "^8.57.0",
"eslint-config-next": "14.2.5",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"postcss": "^8.4.41",
"postcss": "^8.4.44",
"prettier-plugin-tailwindcss": "^0.6.6",
"tailwindcss": "^3.4.10",
"ts-jest": "^29.2.5",