diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e64d44a..115e431 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: workspaces: ". -> target" - name: Run server tests - run: cargo test -p notto-server + run: cargo test -p nooto-server test-rust-client: name: Rust Client Tests @@ -50,7 +50,7 @@ jobs: workspaces: ". -> target" - name: Run client tests - run: cargo test -p notto + run: cargo test -p nooto test-frontend: name: Frontend Tests @@ -62,12 +62,12 @@ jobs: with: node-version: 22 cache: npm - cache-dependency-path: notto-client/package-lock.json + cache-dependency-path: client/package-lock.json - name: Install dependencies - working-directory: notto-client + working-directory: client run: npm ci - name: Run Vitest - working-directory: notto-client + working-directory: client run: npm test diff --git a/AGENTS.md b/AGENTS.md index a2e187a..5305db4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -13,7 +13,7 @@ git checkout -b claude-dev # Create and switch to claude-dev branch ## Project Overview -Notto is an end-to-end encrypted note-taking application built with: +Nooto is an end-to-end encrypted note-taking application built with: - **Client**: Tauri v2 desktop app (Rust backend + React frontend with TypeScript) - **Server**: Axum HTTP server for sync - **Database**: MariaDB (server), SQLite (client) @@ -23,7 +23,7 @@ Notto is an end-to-end encrypted note-taking application built with: ### Frontend (Tauri Client) ```bash -cd notto-client +cd nooto-client npm install # Install dependencies npm run tauri dev # Run development mode npm run build # Build TypeScript @@ -32,7 +32,7 @@ npm run tauri build # Build production app ### Backend (Sync Server) ```bash -cd notto-server +cd server cargo run # Run development server (listens on 0.0.0.0:3000) cargo build --release # Build production binary ``` @@ -44,7 +44,7 @@ docker-compose up # Start MariaDB and Adminer (port 8080) docker-compose down # Stop services ``` -Database connection string must be set in `notto-server/.env` as `DATABASE_URL`. +Database connection string must be set in `server/.env` as `DATABASE_URL`. ### Workspace Commands From project root: @@ -58,8 +58,8 @@ cargo test # Run tests for all crates ### Workspace Structure This is a Cargo workspace with three members: - `shared/`: Common types and structs shared between client and server -- `notto-client/src-tauri/`: Tauri backend (Rust) -- `notto-server/`: HTTP sync server (Axum) +- `client/src-tauri/`: Tauri backend (Rust) +- `server/`: HTTP sync server (Axum) ### Client Architecture (Tauri) diff --git a/Cargo.toml b/Cargo.toml index 7736430..ceb04d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,3 @@ [workspace] resolver = "3" -members = ["shared", "notto-client/src-tauri", "notto-server"] \ No newline at end of file +members = ["shared", "client/src-tauri", "server"] \ No newline at end of file diff --git a/README.md b/README.md index 59c743f..aaf6131 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Notto +# Nooto See [Technical infos](./technical_infos.md) file for more informations on what I'm building. diff --git a/notto-client/index.html b/client/index.html similarity index 75% rename from notto-client/index.html rename to client/index.html index 844dcc2..8c5cab9 100644 --- a/notto-client/index.html +++ b/client/index.html @@ -2,9 +2,9 @@ - + - Notto + Nooto diff --git a/notto-client/package-lock.json b/client/package-lock.json similarity index 99% rename from notto-client/package-lock.json rename to client/package-lock.json index 88c2b4f..0706921 100644 --- a/notto-client/package-lock.json +++ b/client/package-lock.json @@ -1,11 +1,11 @@ { - "name": "notto", + "name": "nooto", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "notto", + "name": "nooto", "version": "0.1.0", "dependencies": { "@dnd-kit/core": "^6.3.1", diff --git a/notto-client/package.json b/client/package.json similarity index 98% rename from notto-client/package.json rename to client/package.json index 5410ebc..b660f99 100644 --- a/notto-client/package.json +++ b/client/package.json @@ -1,5 +1,5 @@ { - "name": "notto", + "name": "nooto", "private": true, "version": "0.1.0", "type": "module", diff --git a/notto-client/public/notto.svg b/client/public/notto.svg similarity index 100% rename from notto-client/public/notto.svg rename to client/public/notto.svg diff --git a/notto-client/public/tauri.svg b/client/public/tauri.svg similarity index 100% rename from notto-client/public/tauri.svg rename to client/public/tauri.svg diff --git a/notto-client/public/vite.svg b/client/public/vite.svg similarity index 100% rename from notto-client/public/vite.svg rename to client/public/vite.svg diff --git a/notto-client/src-tauri/.gitignore b/client/src-tauri/.gitignore similarity index 100% rename from notto-client/src-tauri/.gitignore rename to client/src-tauri/.gitignore diff --git a/notto-client/src-tauri/Cargo.toml b/client/src-tauri/Cargo.toml similarity index 98% rename from notto-client/src-tauri/Cargo.toml rename to client/src-tauri/Cargo.toml index b96bef6..dd01819 100644 --- a/notto-client/src-tauri/Cargo.toml +++ b/client/src-tauri/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "notto" +name = "nooto" version = "0.0.15" description = "A Tauri App" authors = ["Clément Pera"] diff --git a/notto-client/src-tauri/build.rs b/client/src-tauri/build.rs similarity index 100% rename from notto-client/src-tauri/build.rs rename to client/src-tauri/build.rs diff --git a/notto-client/src-tauri/capabilities/default.json b/client/src-tauri/capabilities/default.json similarity index 100% rename from notto-client/src-tauri/capabilities/default.json rename to client/src-tauri/capabilities/default.json diff --git a/notto-client/src-tauri/gen/android/.editorconfig b/client/src-tauri/gen/android/.editorconfig similarity index 100% rename from notto-client/src-tauri/gen/android/.editorconfig rename to client/src-tauri/gen/android/.editorconfig diff --git a/notto-client/src-tauri/gen/android/.gitignore b/client/src-tauri/gen/android/.gitignore similarity index 100% rename from notto-client/src-tauri/gen/android/.gitignore rename to client/src-tauri/gen/android/.gitignore diff --git a/notto-client/src-tauri/gen/android/app/.gitignore b/client/src-tauri/gen/android/app/.gitignore similarity index 75% rename from notto-client/src-tauri/gen/android/app/.gitignore rename to client/src-tauri/gen/android/app/.gitignore index d581a63..9555952 100644 --- a/notto-client/src-tauri/gen/android/app/.gitignore +++ b/client/src-tauri/gen/android/app/.gitignore @@ -1,4 +1,4 @@ -/src/main/java/com/notto/app/generated +/src/main/java/com/nooto/app/generated /src/main/jniLibs/**/*.so /src/main/assets/tauri.conf.json /tauri.build.gradle.kts diff --git a/notto-client/src-tauri/gen/android/app/build.gradle.kts b/client/src-tauri/gen/android/app/build.gradle.kts similarity index 96% rename from notto-client/src-tauri/gen/android/app/build.gradle.kts rename to client/src-tauri/gen/android/app/build.gradle.kts index fafdbe6..3373f0c 100644 --- a/notto-client/src-tauri/gen/android/app/build.gradle.kts +++ b/client/src-tauri/gen/android/app/build.gradle.kts @@ -15,10 +15,10 @@ val tauriProperties = Properties().apply { android { compileSdk = 36 - namespace = "com.notto.app" + namespace = "com.nooto.app" defaultConfig { manifestPlaceholders["usesCleartextTraffic"] = "false" - applicationId = "com.notto.app" + applicationId = "com.nooto.app" minSdk = 24 targetSdk = 36 versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt() diff --git a/notto-client/src-tauri/gen/android/app/proguard-rules.pro b/client/src-tauri/gen/android/app/proguard-rules.pro similarity index 100% rename from notto-client/src-tauri/gen/android/app/proguard-rules.pro rename to client/src-tauri/gen/android/app/proguard-rules.pro diff --git a/notto-client/src-tauri/gen/android/app/src/main/AndroidManifest.xml b/client/src-tauri/gen/android/app/src/main/AndroidManifest.xml similarity index 97% rename from notto-client/src-tauri/gen/android/app/src/main/AndroidManifest.xml rename to client/src-tauri/gen/android/app/src/main/AndroidManifest.xml index 37296ea..fa71e1a 100644 --- a/notto-client/src-tauri/gen/android/app/src/main/AndroidManifest.xml +++ b/client/src-tauri/gen/android/app/src/main/AndroidManifest.xml @@ -8,7 +8,7 @@ + // we're not using WebView::getUrl() here because it needs to be executed on the main thread + // and it would slow down the Ipc + // so instead we track the current URL on the webview client + this.ipc(webViewClient.currentUrl, m) + } + } + + companion object { + init { + System.loadLibrary("notto_lib") + } + } + + private external fun ipc(url: String, message: String) + + +} diff --git a/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/Logger.kt b/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/Logger.kt new file mode 100644 index 0000000..8fd08e8 --- /dev/null +++ b/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/Logger.kt @@ -0,0 +1,89 @@ +/* THIS FILE IS AUTO-GENERATED. DO NOT MODIFY!! */ + +// Copyright 2020-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +@file:Suppress("unused", "MemberVisibilityCanBePrivate") + +package com.notto.app + +// taken from https://github.com/ionic-team/capacitor/blob/6658bca41e78239347e458175b14ca8bd5c1d6e8/android/capacitor/src/main/java/com/getcapacitor/Logger.java + +import android.text.TextUtils +import android.util.Log + +class Logger { + companion object { + private const val LOG_TAG_CORE = "Tauri" + + fun tags(vararg subtags: String): String { + return if (subtags.isNotEmpty()) { + LOG_TAG_CORE + "/" + TextUtils.join("/", subtags) + } else LOG_TAG_CORE + } + + fun verbose(message: String) { + verbose(LOG_TAG_CORE, message) + } + + private fun verbose(tag: String, message: String) { + if (!shouldLog()) { + return + } + Log.v(tag, message) + } + + fun debug(message: String) { + debug(LOG_TAG_CORE, message) + } + + fun debug(tag: String, message: String) { + if (!shouldLog()) { + return + } + Log.d(tag, message) + } + + fun info(message: String) { + info(LOG_TAG_CORE, message) + } + + fun info(tag: String, message: String) { + if (!shouldLog()) { + return + } + Log.i(tag, message) + } + + fun warn(message: String) { + warn(LOG_TAG_CORE, message) + } + + fun warn(tag: String, message: String) { + if (!shouldLog()) { + return + } + Log.w(tag, message) + } + + fun error(message: String) { + error(LOG_TAG_CORE, message, null) + } + + fun error(message: String, e: Throwable?) { + error(LOG_TAG_CORE, message, e) + } + + fun error(tag: String, message: String, e: Throwable?) { + if (!shouldLog()) { + return + } + Log.e(tag, message, e) + } + + private fun shouldLog(): Boolean { + return BuildConfig.DEBUG + } + } +} diff --git a/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/PermissionHelper.kt b/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/PermissionHelper.kt new file mode 100644 index 0000000..840473e --- /dev/null +++ b/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/PermissionHelper.kt @@ -0,0 +1,117 @@ +/* THIS FILE IS AUTO-GENERATED. DO NOT MODIFY!! */ + +// Copyright 2020-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +package com.notto.app + +// taken from https://github.com/ionic-team/capacitor/blob/6658bca41e78239347e458175b14ca8bd5c1d6e8/android/capacitor/src/main/java/com/getcapacitor/PermissionHelper.java + +import android.content.Context +import android.content.pm.PackageManager +import android.os.Build +import androidx.core.app.ActivityCompat +import java.util.ArrayList + +object PermissionHelper { + /** + * Checks if a list of given permissions are all granted by the user + * + * @param permissions Permissions to check. + * @return True if all permissions are granted, false if at least one is not. + */ + fun hasPermissions(context: Context?, permissions: Array): Boolean { + for (perm in permissions) { + if (ActivityCompat.checkSelfPermission( + context!!, + perm + ) != PackageManager.PERMISSION_GRANTED + ) { + return false + } + } + return true + } + + /** + * Check whether the given permission has been defined in the AndroidManifest.xml + * + * @param permission A permission to check. + * @return True if the permission has been defined in the Manifest, false if not. + */ + fun hasDefinedPermission(context: Context, permission: String): Boolean { + var hasPermission = false + val requestedPermissions = getManifestPermissions(context) + if (!requestedPermissions.isNullOrEmpty()) { + val requestedPermissionsList = listOf(*requestedPermissions) + val requestedPermissionsArrayList = ArrayList(requestedPermissionsList) + if (requestedPermissionsArrayList.contains(permission)) { + hasPermission = true + } + } + return hasPermission + } + + /** + * Check whether all of the given permissions have been defined in the AndroidManifest.xml + * @param context the app context + * @param permissions a list of permissions + * @return true only if all permissions are defined in the AndroidManifest.xml + */ + fun hasDefinedPermissions(context: Context, permissions: Array): Boolean { + for (permission in permissions) { + if (!hasDefinedPermission(context, permission)) { + return false + } + } + return true + } + + /** + * Get the permissions defined in AndroidManifest.xml + * + * @return The permissions defined in AndroidManifest.xml + */ + private fun getManifestPermissions(context: Context): Array? { + var requestedPermissions: Array? = null + try { + val pm = context.packageManager + val packageInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + pm.getPackageInfo(context.packageName, PackageManager.PackageInfoFlags.of(PackageManager.GET_PERMISSIONS.toLong())) + } else { + @Suppress("DEPRECATION") + pm.getPackageInfo(context.packageName, PackageManager.GET_PERMISSIONS) + } + if (packageInfo != null) { + requestedPermissions = packageInfo.requestedPermissions + } + } catch (_: Exception) { + } + return requestedPermissions + } + + /** + * Given a list of permissions, return a new list with the ones not present in AndroidManifest.xml + * + * @param neededPermissions The permissions needed. + * @return The permissions not present in AndroidManifest.xml + */ + fun getUndefinedPermissions(context: Context, neededPermissions: Array): Array { + val undefinedPermissions = ArrayList() + val requestedPermissions = getManifestPermissions(context) + if (!requestedPermissions.isNullOrEmpty()) { + val requestedPermissionsList = listOf(*requestedPermissions) + val requestedPermissionsArrayList = ArrayList(requestedPermissionsList) + for (permission in neededPermissions) { + if (!requestedPermissionsArrayList.contains(permission)) { + undefinedPermissions.add(permission) + } + } + var undefinedPermissionArray = arrayOfNulls(undefinedPermissions.size) + undefinedPermissionArray = undefinedPermissions.toArray(undefinedPermissionArray) + return undefinedPermissionArray + } + return neededPermissions + } +} diff --git a/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/RustWebChromeClient.kt b/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/RustWebChromeClient.kt new file mode 100644 index 0000000..6f92614 --- /dev/null +++ b/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/RustWebChromeClient.kt @@ -0,0 +1,495 @@ +/* THIS FILE IS AUTO-GENERATED. DO NOT MODIFY!! */ + +// Copyright 2020-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +@file:Suppress("ObsoleteSdkInt", "RedundantOverride", "QueryPermissionsNeeded", "SimpleDateFormat") + +package com.notto.app + +// taken from https://github.com/ionic-team/capacitor/blob/6658bca41e78239347e458175b14ca8bd5c1d6e8/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java + +import android.Manifest +import android.app.Activity +import android.app.AlertDialog +import android.content.ActivityNotFoundException +import android.content.DialogInterface +import android.content.Intent +import android.net.Uri +import android.os.Build +import android.os.Environment +import android.provider.MediaStore +import android.view.View +import android.webkit.* +import android.widget.EditText +import androidx.activity.result.ActivityResult +import androidx.activity.result.ActivityResultCallback +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.content.FileProvider +import java.io.File +import java.io.IOException +import java.text.SimpleDateFormat +import java.util.* + +class RustWebChromeClient(appActivity: WryActivity) : WebChromeClient() { + private interface PermissionListener { + fun onPermissionSelect(isGranted: Boolean?) + } + + private interface ActivityResultListener { + fun onActivityResult(result: ActivityResult?) + } + + private val activity: WryActivity + private var permissionLauncher: ActivityResultLauncher> + private var activityLauncher: ActivityResultLauncher + private var permissionListener: PermissionListener? = null + private var activityListener: ActivityResultListener? = null + + init { + activity = appActivity + val permissionCallback = + ActivityResultCallback { isGranted: Map -> + if (permissionListener != null) { + var granted = true + for ((_, value) in isGranted) { + if (!value) granted = false + } + permissionListener!!.onPermissionSelect(granted) + } + } + permissionLauncher = + activity.registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions(), permissionCallback) + activityLauncher = activity.registerForActivityResult( + ActivityResultContracts.StartActivityForResult() + ) { result -> + if (activityListener != null) { + activityListener!!.onActivityResult(result) + } + } + } + + /** + * Render web content in `view`. + * + * Both this method and [.onHideCustomView] are required for + * rendering web content in full screen. + * + * @see [](https://developer.android.com/reference/android/webkit/WebChromeClient.onShowCustomView + ) */ + override fun onShowCustomView(view: View, callback: CustomViewCallback) { + callback.onCustomViewHidden() + super.onShowCustomView(view, callback) + } + + /** + * Render web content in the original Web View again. + * + * Do not remove this method--@see #onShowCustomView(View, CustomViewCallback). + */ + override fun onHideCustomView() { + super.onHideCustomView() + } + + override fun onPermissionRequest(request: PermissionRequest) { + val isRequestPermissionRequired = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M + val permissionList: MutableList = ArrayList() + if (listOf(*request.resources).contains("android.webkit.resource.VIDEO_CAPTURE")) { + permissionList.add(Manifest.permission.CAMERA) + } + if (listOf(*request.resources).contains("android.webkit.resource.AUDIO_CAPTURE")) { + permissionList.add(Manifest.permission.MODIFY_AUDIO_SETTINGS) + permissionList.add(Manifest.permission.RECORD_AUDIO) + } + if (permissionList.isNotEmpty() && isRequestPermissionRequired) { + val permissions = permissionList.toTypedArray() + permissionListener = object : PermissionListener { + override fun onPermissionSelect(isGranted: Boolean?) { + if (isGranted == true) { + request.grant(request.resources) + } else { + request.deny() + } + } + } + permissionLauncher.launch(permissions) + } else { + request.grant(request.resources) + } + } + + /** + * Show the browser alert modal + * @param view + * @param url + * @param message + * @param result + * @return + */ + override fun onJsAlert(view: WebView, url: String, message: String, result: JsResult): Boolean { + if (activity.isFinishing) { + return true + } + val builder = AlertDialog.Builder(view.context) + builder + .setMessage(message) + .setPositiveButton( + "OK" + ) { dialog: DialogInterface, _: Int -> + dialog.dismiss() + result.confirm() + } + .setOnCancelListener { dialog: DialogInterface -> + dialog.dismiss() + result.cancel() + } + val dialog = builder.create() + dialog.show() + return true + } + + /** + * Show the browser confirm modal + * @param view + * @param url + * @param message + * @param result + * @return + */ + override fun onJsConfirm(view: WebView, url: String, message: String, result: JsResult): Boolean { + if (activity.isFinishing) { + return true + } + val builder = AlertDialog.Builder(view.context) + builder + .setMessage(message) + .setPositiveButton( + "OK" + ) { dialog: DialogInterface, _: Int -> + dialog.dismiss() + result.confirm() + } + .setNegativeButton( + "Cancel" + ) { dialog: DialogInterface, _: Int -> + dialog.dismiss() + result.cancel() + } + .setOnCancelListener { dialog: DialogInterface -> + dialog.dismiss() + result.cancel() + } + val dialog = builder.create() + dialog.show() + return true + } + + /** + * Show the browser prompt modal + * @param view + * @param url + * @param message + * @param defaultValue + * @param result + * @return + */ + override fun onJsPrompt( + view: WebView, + url: String, + message: String, + defaultValue: String, + result: JsPromptResult + ): Boolean { + if (activity.isFinishing) { + return true + } + val builder = AlertDialog.Builder(view.context) + val input = EditText(view.context) + builder + .setMessage(message) + .setView(input) + .setPositiveButton( + "OK" + ) { dialog: DialogInterface, _: Int -> + dialog.dismiss() + val inputText1 = input.text.toString().trim { it <= ' ' } + result.confirm(inputText1) + } + .setNegativeButton( + "Cancel" + ) { dialog: DialogInterface, _: Int -> + dialog.dismiss() + result.cancel() + } + .setOnCancelListener { dialog: DialogInterface -> + dialog.dismiss() + result.cancel() + } + val dialog = builder.create() + dialog.show() + return true + } + + /** + * Handle the browser geolocation permission prompt + * @param origin + * @param callback + */ + override fun onGeolocationPermissionsShowPrompt( + origin: String, + callback: GeolocationPermissions.Callback + ) { + super.onGeolocationPermissionsShowPrompt(origin, callback) + Logger.debug("onGeolocationPermissionsShowPrompt: DOING IT HERE FOR ORIGIN: $origin") + val geoPermissions = + arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION) + if (!PermissionHelper.hasPermissions(activity, geoPermissions)) { + permissionListener = object : PermissionListener { + override fun onPermissionSelect(isGranted: Boolean?) { + if (isGranted == true) { + callback.invoke(origin, true, false) + } else { + val coarsePermission = + arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && + PermissionHelper.hasPermissions(activity, coarsePermission) + ) { + callback.invoke(origin, true, false) + } else { + callback.invoke(origin, false, false) + } + } + } + } + permissionLauncher.launch(geoPermissions) + } else { + // permission is already granted + callback.invoke(origin, true, false) + Logger.debug("onGeolocationPermissionsShowPrompt: has required permission") + } + } + + override fun onShowFileChooser( + webView: WebView, + filePathCallback: ValueCallback?>, + fileChooserParams: FileChooserParams + ): Boolean { + val acceptTypes = listOf(*fileChooserParams.acceptTypes) + val captureEnabled = fileChooserParams.isCaptureEnabled + val capturePhoto = captureEnabled && acceptTypes.contains("image/*") + val captureVideo = captureEnabled && acceptTypes.contains("video/*") + if (capturePhoto || captureVideo) { + if (isMediaCaptureSupported) { + showMediaCaptureOrFilePicker(filePathCallback, fileChooserParams, captureVideo) + } else { + permissionListener = object : PermissionListener { + override fun onPermissionSelect(isGranted: Boolean?) { + if (isGranted == true) { + showMediaCaptureOrFilePicker(filePathCallback, fileChooserParams, captureVideo) + } else { + Logger.warn(Logger.tags("FileChooser"), "Camera permission not granted") + filePathCallback.onReceiveValue(null) + } + } + } + val camPermission = arrayOf(Manifest.permission.CAMERA) + permissionLauncher.launch(camPermission) + } + } else { + showFilePicker(filePathCallback, fileChooserParams) + } + return true + } + + private val isMediaCaptureSupported: Boolean + get() { + val permissions = arrayOf(Manifest.permission.CAMERA) + return PermissionHelper.hasPermissions(activity, permissions) || + !PermissionHelper.hasDefinedPermission(activity, Manifest.permission.CAMERA) + } + + private fun showMediaCaptureOrFilePicker( + filePathCallback: ValueCallback?>, + fileChooserParams: FileChooserParams, + isVideo: Boolean + ) { + val isVideoCaptureSupported = true + val shown = if (isVideo && isVideoCaptureSupported) { + showVideoCapturePicker(filePathCallback) + } else { + showImageCapturePicker(filePathCallback) + } + if (!shown) { + Logger.warn( + Logger.tags("FileChooser"), + "Media capture intent could not be launched. Falling back to default file picker." + ) + showFilePicker(filePathCallback, fileChooserParams) + } + } + + private fun showImageCapturePicker(filePathCallback: ValueCallback?>): Boolean { + val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) + if (takePictureIntent.resolveActivity(activity.packageManager) == null) { + return false + } + val imageFileUri: Uri = try { + createImageFileUri() + } catch (ex: Exception) { + Logger.error("Unable to create temporary media capture file: " + ex.message) + return false + } + takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri) + activityListener = object : ActivityResultListener { + override fun onActivityResult(result: ActivityResult?) { + var res: Array? = null + if (result?.resultCode == Activity.RESULT_OK) { + res = arrayOf(imageFileUri) + } + filePathCallback.onReceiveValue(res) + } + } + activityLauncher.launch(takePictureIntent) + return true + } + + private fun showVideoCapturePicker(filePathCallback: ValueCallback?>): Boolean { + val takeVideoIntent = Intent(MediaStore.ACTION_VIDEO_CAPTURE) + if (takeVideoIntent.resolveActivity(activity.packageManager) == null) { + return false + } + activityListener = object : ActivityResultListener { + override fun onActivityResult(result: ActivityResult?) { + var res: Array? = null + if (result?.resultCode == Activity.RESULT_OK) { + res = arrayOf(result.data!!.data) + } + filePathCallback.onReceiveValue(res) + } + } + activityLauncher.launch(takeVideoIntent) + return true + } + + private fun showFilePicker( + filePathCallback: ValueCallback?>, + fileChooserParams: FileChooserParams + ) { + val intent = fileChooserParams.createIntent() + if (fileChooserParams.mode == FileChooserParams.MODE_OPEN_MULTIPLE) { + intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true) + } + if (fileChooserParams.acceptTypes.size > 1 || intent.type!!.startsWith(".")) { + val validTypes = getValidTypes(fileChooserParams.acceptTypes) + intent.putExtra(Intent.EXTRA_MIME_TYPES, validTypes) + if (intent.type!!.startsWith(".")) { + intent.type = validTypes[0] + } + } + try { + activityListener = object : ActivityResultListener { + override fun onActivityResult(result: ActivityResult?) { + val res: Array? + val resultIntent = result?.data + if (result?.resultCode == Activity.RESULT_OK && resultIntent!!.clipData != null) { + val numFiles = resultIntent.clipData!!.itemCount + res = arrayOfNulls(numFiles) + for (i in 0 until numFiles) { + res[i] = resultIntent.clipData!!.getItemAt(i).uri + } + } else { + res = FileChooserParams.parseResult( + result?.resultCode ?: 0, + resultIntent + ) + } + filePathCallback.onReceiveValue(res) + } + } + activityLauncher.launch(intent) + } catch (e: ActivityNotFoundException) { + filePathCallback.onReceiveValue(null) + } + } + + private fun getValidTypes(currentTypes: Array): Array { + val validTypes: MutableList = ArrayList() + val mtm = MimeTypeMap.getSingleton() + for (mime in currentTypes) { + if (mime.startsWith(".")) { + val extension = mime.substring(1) + val extensionMime = mtm.getMimeTypeFromExtension(extension) + if (extensionMime != null && !validTypes.contains(extensionMime)) { + validTypes.add(extensionMime) + } + } else if (!validTypes.contains(mime)) { + validTypes.add(mime) + } + } + val validObj: Array = validTypes.toTypedArray() + return Arrays.copyOf( + validObj, validObj.size, + Array::class.java + ) + } + + override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean { + val tag: String = Logger.tags("Console") + if (consoleMessage.message() != null && isValidMsg(consoleMessage.message())) { + val msg = String.format( + "File: %s - Line %d - Msg: %s", + consoleMessage.sourceId(), + consoleMessage.lineNumber(), + consoleMessage.message() + ) + val level = consoleMessage.messageLevel().name + if ("ERROR".equals(level, ignoreCase = true)) { + Logger.error(tag, msg, null) + } else if ("WARNING".equals(level, ignoreCase = true)) { + Logger.warn(tag, msg) + } else if ("TIP".equals(level, ignoreCase = true)) { + Logger.debug(tag, msg) + } else { + Logger.info(tag, msg) + } + } + return true + } + + private fun isValidMsg(msg: String): Boolean { + return !(msg.contains("%cresult %c") || + msg.contains("%cnative %c") || + msg.equals("[object Object]", ignoreCase = true) || + msg.equals("console.groupEnd", ignoreCase = true)) + } + + @Throws(IOException::class) + private fun createImageFileUri(): Uri { + val photoFile = createImageFile(activity) + return FileProvider.getUriForFile( + activity, + activity.packageName.toString() + ".fileprovider", + photoFile + ) + } + + @Throws(IOException::class) + private fun createImageFile(activity: Activity): File { + // Create an image file name + val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date()) + val imageFileName = "JPEG_" + timeStamp + "_" + val storageDir = activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES) + return File.createTempFile(imageFileName, ".jpg", storageDir) + } + + override fun onReceivedTitle( + view: WebView, + title: String + ) { + handleReceivedTitle(view, title) + } + + private external fun handleReceivedTitle(webview: WebView, title: String) +} diff --git a/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/RustWebView.kt b/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/RustWebView.kt new file mode 100644 index 0000000..b4e8d12 --- /dev/null +++ b/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/RustWebView.kt @@ -0,0 +1,101 @@ +/* THIS FILE IS AUTO-GENERATED. DO NOT MODIFY!! */ + +// Copyright 2020-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +@file:Suppress("unused", "SetJavaScriptEnabled") + +package com.notto.app + +import android.annotation.SuppressLint +import android.webkit.* +import android.content.Context +import androidx.webkit.WebViewCompat +import androidx.webkit.WebViewFeature +import kotlin.collections.Map + +@SuppressLint("RestrictedApi") +class RustWebView(context: Context, val initScripts: Array, val id: String): WebView(context) { + val isDocumentStartScriptEnabled: Boolean + + init { + settings.javaScriptEnabled = true + settings.domStorageEnabled = true + settings.setGeolocationEnabled(true) + settings.databaseEnabled = true + settings.mediaPlaybackRequiresUserGesture = false + settings.javaScriptCanOpenWindowsAutomatically = true + + if (WebViewFeature.isFeatureSupported(WebViewFeature.DOCUMENT_START_SCRIPT)) { + isDocumentStartScriptEnabled = true + for (script in initScripts) { + WebViewCompat.addDocumentStartJavaScript(this, script, setOf("*")); + } + } else { + isDocumentStartScriptEnabled = false + } + + + } + + fun loadUrlMainThread(url: String) { + post { + loadUrl(url) + } + } + + fun loadUrlMainThread(url: String, additionalHttpHeaders: Map) { + post { + loadUrl(url, additionalHttpHeaders) + } + } + + override fun loadUrl(url: String) { + if (!shouldOverride(url)) { + super.loadUrl(url); + } + } + + override fun loadUrl(url: String, additionalHttpHeaders: Map) { + if (!shouldOverride(url)) { + super.loadUrl(url, additionalHttpHeaders); + } + } + + fun loadHTMLMainThread(html: String) { + post { + super.loadData(html, "text/html", null) + } + } + + fun evalScript(id: Int, script: String) { + post { + super.evaluateJavascript(script) { result -> + onEval(id, result) + } + } + } + + fun clearAllBrowsingData() { + try { + super.getContext().deleteDatabase("webviewCache.db") + super.getContext().deleteDatabase("webview.db") + super.clearCache(true) + super.clearHistory() + super.clearFormData() + } catch (ex: Exception) { + Logger.error("Unable to create temporary media capture file: " + ex.message) + } + } + + fun getCookies(url: String): String { + val cookieManager = CookieManager.getInstance() + return cookieManager.getCookie(url) + } + + private external fun shouldOverride(url: String): Boolean + private external fun onEval(id: Int, result: String) + + +} diff --git a/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/RustWebViewClient.kt b/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/RustWebViewClient.kt new file mode 100644 index 0000000..cb8276b --- /dev/null +++ b/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/RustWebViewClient.kt @@ -0,0 +1,107 @@ +/* THIS FILE IS AUTO-GENERATED. DO NOT MODIFY!! */ + +// Copyright 2020-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +package com.notto.app + +import android.net.Uri +import android.webkit.* +import android.content.Context +import android.graphics.Bitmap +import android.os.Handler +import android.os.Looper +import androidx.webkit.WebViewAssetLoader + +class RustWebViewClient(context: Context): WebViewClient() { + private val interceptedState = mutableMapOf() + var currentUrl: String = "about:blank" + private var lastInterceptedUrl: Uri? = null + private var pendingUrlRedirect: String? = null + + private val assetLoader = WebViewAssetLoader.Builder() + .setDomain(assetLoaderDomain()) + .addPathHandler("/", WebViewAssetLoader.AssetsPathHandler(context)) + .build() + + override fun shouldInterceptRequest( + view: WebView, + request: WebResourceRequest + ): WebResourceResponse? { + pendingUrlRedirect?.let { + Handler(Looper.getMainLooper()).post { + view.loadUrl(it) + } + pendingUrlRedirect = null + return null + } + + lastInterceptedUrl = request.url + return if (withAssetLoader()) { + assetLoader.shouldInterceptRequest(request.url) + } else { + val rustWebview = view as RustWebView; + val response = handleRequest(rustWebview.id, request, rustWebview.isDocumentStartScriptEnabled) + interceptedState[request.url.toString()] = response != null + return response + } + } + + override fun shouldOverrideUrlLoading( + view: WebView, + request: WebResourceRequest + ): Boolean { + return shouldOverride(request.url.toString()) + } + + override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) { + currentUrl = url + if (interceptedState[url] == false) { + val webView = view as RustWebView + for (script in webView.initScripts) { + view.evaluateJavascript(script, null) + } + } + return onPageLoading(url) + } + + override fun onPageFinished(view: WebView, url: String) { + onPageLoaded(url) + } + + override fun onReceivedError( + view: WebView, + request: WebResourceRequest, + error: WebResourceError + ) { + // we get a net::ERR_CONNECTION_REFUSED when an external URL redirects to a custom protocol + // e.g. oauth flow, because shouldInterceptRequest is not called on redirects + // so we must force retry here with loadUrl() to get a chance of the custom protocol to kick in + if (error.errorCode == ERROR_CONNECT && request.isForMainFrame && request.url != lastInterceptedUrl) { + // prevent the default error page from showing + view.stopLoading() + // without this initial loadUrl the app is stuck + view.loadUrl(request.url.toString()) + // ensure the URL is actually loaded - for some reason there's a race condition and we need to call loadUrl() again later + pendingUrlRedirect = request.url.toString() + } else { + super.onReceivedError(view, request, error) + } + } + + companion object { + init { + System.loadLibrary("notto_lib") + } + } + + private external fun assetLoaderDomain(): String + private external fun withAssetLoader(): Boolean + private external fun handleRequest(webviewId: String, request: WebResourceRequest, isDocumentStartScriptEnabled: Boolean): WebResourceResponse? + private external fun shouldOverride(url: String): Boolean + private external fun onPageLoading(url: String) + private external fun onPageLoaded(url: String) + + +} diff --git a/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/TauriActivity.kt b/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/TauriActivity.kt new file mode 100644 index 0000000..2c00791 --- /dev/null +++ b/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/TauriActivity.kt @@ -0,0 +1,51 @@ +// Copyright 2019-2024 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +/* THIS FILE IS AUTO-GENERATED. DO NOT MODIFY!! */ + +package com.notto.app + +import android.content.Intent +import android.content.res.Configuration +import app.tauri.plugin.PluginManager + +abstract class TauriActivity : WryActivity() { + var pluginManager: PluginManager = PluginManager(this) + override val handleBackNavigation: Boolean = false + + override fun onNewIntent(intent: Intent) { + super.onNewIntent(intent) + pluginManager.onNewIntent(intent) + } + + override fun onResume() { + super.onResume() + pluginManager.onResume() + } + + override fun onPause() { + super.onPause() + pluginManager.onPause() + } + + override fun onRestart() { + super.onRestart() + pluginManager.onRestart() + } + + override fun onStop() { + super.onStop() + pluginManager.onStop() + } + + override fun onDestroy() { + super.onDestroy() + pluginManager.onDestroy() + } + + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + pluginManager.onConfigurationChanged(newConfig) + } +} diff --git a/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/WryActivity.kt b/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/WryActivity.kt new file mode 100644 index 0000000..cbd8a3e --- /dev/null +++ b/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/WryActivity.kt @@ -0,0 +1,137 @@ +/* THIS FILE IS AUTO-GENERATED. DO NOT MODIFY!! */ + +// Copyright 2020-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +package com.notto.app + +import com.notto.app.RustWebView +import android.annotation.SuppressLint +import android.os.Build +import android.os.Bundle +import android.webkit.WebView +import android.view.KeyEvent +import androidx.appcompat.app.AppCompatActivity + +abstract class WryActivity : AppCompatActivity() { + private lateinit var mWebView: RustWebView + open val handleBackNavigation: Boolean = true + + open fun onWebViewCreate(webView: WebView) { } + + fun setWebView(webView: RustWebView) { + mWebView = webView + onWebViewCreate(webView) + } + + val version: String + @SuppressLint("WebViewApiAvailability", "ObsoleteSdkInt") + get() { + // Check getCurrentWebViewPackage() directly if above Android 8 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + return WebView.getCurrentWebViewPackage()?.versionName ?: "" + } + + // Otherwise manually check WebView versions + var webViewPackage = "com.google.android.webview" + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + webViewPackage = "com.android.chrome" + } + try { + @Suppress("DEPRECATION") + val info = packageManager.getPackageInfo(webViewPackage, 0) + return info.versionName.toString() + } catch (ex: Exception) { + Logger.warn("Unable to get package info for '$webViewPackage'$ex") + } + + try { + @Suppress("DEPRECATION") + val info = packageManager.getPackageInfo("com.android.webview", 0) + return info.versionName.toString() + } catch (ex: Exception) { + Logger.warn("Unable to get package info for 'com.android.webview'$ex") + } + + // Could not detect any webview, return empty string + return "" + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + create(this) + } + + override fun onStart() { + super.onStart() + start() + } + + override fun onResume() { + super.onResume() + resume() + } + + override fun onPause() { + super.onPause() + pause() + } + + override fun onStop() { + super.onStop() + stop() + } + + override fun onWindowFocusChanged(hasFocus: Boolean) { + super.onWindowFocusChanged(hasFocus) + focus(hasFocus) + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + save() + } + + override fun onDestroy() { + super.onDestroy() + destroy() + onActivityDestroy() + } + + override fun onLowMemory() { + super.onLowMemory() + memory() + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + if (handleBackNavigation && keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) { + mWebView.goBack() + return true + } + return super.onKeyDown(keyCode, event) + } + + fun getAppClass(name: String): Class<*> { + return Class.forName(name) + } + + companion object { + init { + System.loadLibrary("notto_lib") + } + } + + private external fun create(activity: WryActivity) + private external fun start() + private external fun resume() + private external fun pause() + private external fun stop() + private external fun save() + private external fun destroy() + private external fun onActivityDestroy() + private external fun memory() + private external fun focus(focus: Boolean) + + +} diff --git a/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/proguard-wry.pro b/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/proguard-wry.pro new file mode 100644 index 0000000..33b2b40 --- /dev/null +++ b/client/src-tauri/gen/android/app/src/main/java/com/notto/app/generated/proguard-wry.pro @@ -0,0 +1,35 @@ +# THIS FILE IS AUTO-GENERATED. DO NOT MODIFY!! + +# Copyright 2020-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT + +-keep class com.notto.app.* { + native ; +} + +-keep class com.notto.app.WryActivity { + public (...); + + void setWebView(com.notto.app.RustWebView); + java.lang.Class getAppClass(...); + java.lang.String getVersion(); +} + +-keep class com.notto.app.Ipc { + public (...); + + @android.webkit.JavascriptInterface public ; +} + +-keep class com.notto.app.RustWebView { + public (...); + + void loadUrlMainThread(...); + void loadHTMLMainThread(...); + void evalScript(...); +} + +-keep class com.notto.app.RustWebChromeClient,com.notto.app.RustWebViewClient { + public (...); +} diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/client/src-tauri/gen/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml rename to client/src-tauri/gen/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/drawable/ic_launcher_background.xml b/client/src-tauri/gen/android/app/src/main/res/drawable/ic_launcher_background.xml similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/drawable/ic_launcher_background.xml rename to client/src-tauri/gen/android/app/src/main/res/drawable/ic_launcher_background.xml diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/layout/activity_main.xml b/client/src-tauri/gen/android/app/src/main/res/layout/activity_main.xml similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/layout/activity_main.xml rename to client/src-tauri/gen/android/app/src/main/res/layout/activity_main.xml diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/client/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher.png rename to client/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/client/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png rename to client/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/client/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png rename to client/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/client/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher.png rename to client/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/client/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png rename to client/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/client/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png rename to client/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/client/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png rename to client/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/client/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png rename to client/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/client/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png rename to client/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/client/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to client/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/client/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png rename to client/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/client/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png rename to client/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/client/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png rename to client/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/client/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png rename to client/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/client/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png rename to client/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/values-night/themes.xml b/client/src-tauri/gen/android/app/src/main/res/values-night/themes.xml similarity index 74% rename from notto-client/src-tauri/gen/android/app/src/main/res/values-night/themes.xml rename to client/src-tauri/gen/android/app/src/main/res/values-night/themes.xml index 938501c..0b42a12 100644 --- a/notto-client/src-tauri/gen/android/app/src/main/res/values-night/themes.xml +++ b/client/src-tauri/gen/android/app/src/main/res/values-night/themes.xml @@ -1,6 +1,6 @@ - diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/values/colors.xml b/client/src-tauri/gen/android/app/src/main/res/values/colors.xml similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/values/colors.xml rename to client/src-tauri/gen/android/app/src/main/res/values/colors.xml diff --git a/client/src-tauri/gen/android/app/src/main/res/values/strings.xml b/client/src-tauri/gen/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..52f6c33 --- /dev/null +++ b/client/src-tauri/gen/android/app/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + nooto + nooto + \ No newline at end of file diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/values/themes.xml b/client/src-tauri/gen/android/app/src/main/res/values/themes.xml similarity index 74% rename from notto-client/src-tauri/gen/android/app/src/main/res/values/themes.xml rename to client/src-tauri/gen/android/app/src/main/res/values/themes.xml index 938501c..0b42a12 100644 --- a/notto-client/src-tauri/gen/android/app/src/main/res/values/themes.xml +++ b/client/src-tauri/gen/android/app/src/main/res/values/themes.xml @@ -1,6 +1,6 @@ - diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/xml/file_paths.xml b/client/src-tauri/gen/android/app/src/main/res/xml/file_paths.xml similarity index 100% rename from notto-client/src-tauri/gen/android/app/src/main/res/xml/file_paths.xml rename to client/src-tauri/gen/android/app/src/main/res/xml/file_paths.xml diff --git a/notto-client/src-tauri/gen/android/build.gradle.kts b/client/src-tauri/gen/android/build.gradle.kts similarity index 100% rename from notto-client/src-tauri/gen/android/build.gradle.kts rename to client/src-tauri/gen/android/build.gradle.kts diff --git a/notto-client/src-tauri/gen/android/buildSrc/build.gradle.kts b/client/src-tauri/gen/android/buildSrc/build.gradle.kts similarity index 100% rename from notto-client/src-tauri/gen/android/buildSrc/build.gradle.kts rename to client/src-tauri/gen/android/buildSrc/build.gradle.kts diff --git a/notto-client/src-tauri/gen/android/buildSrc/src/main/java/com/notto/app/kotlin/BuildTask.kt b/client/src-tauri/gen/android/buildSrc/src/main/java/com/notto/app/kotlin/BuildTask.kt similarity index 100% rename from notto-client/src-tauri/gen/android/buildSrc/src/main/java/com/notto/app/kotlin/BuildTask.kt rename to client/src-tauri/gen/android/buildSrc/src/main/java/com/notto/app/kotlin/BuildTask.kt diff --git a/notto-client/src-tauri/gen/android/buildSrc/src/main/java/com/notto/app/kotlin/RustPlugin.kt b/client/src-tauri/gen/android/buildSrc/src/main/java/com/notto/app/kotlin/RustPlugin.kt similarity index 100% rename from notto-client/src-tauri/gen/android/buildSrc/src/main/java/com/notto/app/kotlin/RustPlugin.kt rename to client/src-tauri/gen/android/buildSrc/src/main/java/com/notto/app/kotlin/RustPlugin.kt diff --git a/notto-client/src-tauri/gen/android/gradle.properties b/client/src-tauri/gen/android/gradle.properties similarity index 100% rename from notto-client/src-tauri/gen/android/gradle.properties rename to client/src-tauri/gen/android/gradle.properties diff --git a/notto-client/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.jar b/client/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from notto-client/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.jar rename to client/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.jar diff --git a/notto-client/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.properties b/client/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from notto-client/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.properties rename to client/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.properties diff --git a/notto-client/src-tauri/gen/android/gradlew b/client/src-tauri/gen/android/gradlew similarity index 100% rename from notto-client/src-tauri/gen/android/gradlew rename to client/src-tauri/gen/android/gradlew diff --git a/notto-client/src-tauri/gen/android/gradlew.bat b/client/src-tauri/gen/android/gradlew.bat similarity index 100% rename from notto-client/src-tauri/gen/android/gradlew.bat rename to client/src-tauri/gen/android/gradlew.bat diff --git a/notto-client/src-tauri/gen/android/settings.gradle b/client/src-tauri/gen/android/settings.gradle similarity index 100% rename from notto-client/src-tauri/gen/android/settings.gradle rename to client/src-tauri/gen/android/settings.gradle diff --git a/notto-client/src-tauri/icons/128x128.png b/client/src-tauri/icons/128x128.png similarity index 100% rename from notto-client/src-tauri/icons/128x128.png rename to client/src-tauri/icons/128x128.png diff --git a/notto-client/src-tauri/icons/128x128@2x.png b/client/src-tauri/icons/128x128@2x.png similarity index 100% rename from notto-client/src-tauri/icons/128x128@2x.png rename to client/src-tauri/icons/128x128@2x.png diff --git a/notto-client/src-tauri/icons/32x32.png b/client/src-tauri/icons/32x32.png similarity index 100% rename from notto-client/src-tauri/icons/32x32.png rename to client/src-tauri/icons/32x32.png diff --git a/notto-client/src-tauri/icons/Square107x107Logo.png b/client/src-tauri/icons/Square107x107Logo.png similarity index 100% rename from notto-client/src-tauri/icons/Square107x107Logo.png rename to client/src-tauri/icons/Square107x107Logo.png diff --git a/notto-client/src-tauri/icons/Square142x142Logo.png b/client/src-tauri/icons/Square142x142Logo.png similarity index 100% rename from notto-client/src-tauri/icons/Square142x142Logo.png rename to client/src-tauri/icons/Square142x142Logo.png diff --git a/notto-client/src-tauri/icons/Square150x150Logo.png b/client/src-tauri/icons/Square150x150Logo.png similarity index 100% rename from notto-client/src-tauri/icons/Square150x150Logo.png rename to client/src-tauri/icons/Square150x150Logo.png diff --git a/notto-client/src-tauri/icons/Square284x284Logo.png b/client/src-tauri/icons/Square284x284Logo.png similarity index 100% rename from notto-client/src-tauri/icons/Square284x284Logo.png rename to client/src-tauri/icons/Square284x284Logo.png diff --git a/notto-client/src-tauri/icons/Square30x30Logo.png b/client/src-tauri/icons/Square30x30Logo.png similarity index 100% rename from notto-client/src-tauri/icons/Square30x30Logo.png rename to client/src-tauri/icons/Square30x30Logo.png diff --git a/notto-client/src-tauri/icons/Square310x310Logo.png b/client/src-tauri/icons/Square310x310Logo.png similarity index 100% rename from notto-client/src-tauri/icons/Square310x310Logo.png rename to client/src-tauri/icons/Square310x310Logo.png diff --git a/notto-client/src-tauri/icons/Square44x44Logo.png b/client/src-tauri/icons/Square44x44Logo.png similarity index 100% rename from notto-client/src-tauri/icons/Square44x44Logo.png rename to client/src-tauri/icons/Square44x44Logo.png diff --git a/notto-client/src-tauri/icons/Square71x71Logo.png b/client/src-tauri/icons/Square71x71Logo.png similarity index 100% rename from notto-client/src-tauri/icons/Square71x71Logo.png rename to client/src-tauri/icons/Square71x71Logo.png diff --git a/notto-client/src-tauri/icons/Square89x89Logo.png b/client/src-tauri/icons/Square89x89Logo.png similarity index 100% rename from notto-client/src-tauri/icons/Square89x89Logo.png rename to client/src-tauri/icons/Square89x89Logo.png diff --git a/notto-client/src-tauri/icons/StoreLogo.png b/client/src-tauri/icons/StoreLogo.png similarity index 100% rename from notto-client/src-tauri/icons/StoreLogo.png rename to client/src-tauri/icons/StoreLogo.png diff --git a/notto-client/src-tauri/icons/icon.icns b/client/src-tauri/icons/icon.icns similarity index 100% rename from notto-client/src-tauri/icons/icon.icns rename to client/src-tauri/icons/icon.icns diff --git a/notto-client/src-tauri/icons/icon.ico b/client/src-tauri/icons/icon.ico similarity index 100% rename from notto-client/src-tauri/icons/icon.ico rename to client/src-tauri/icons/icon.ico diff --git a/notto-client/src-tauri/icons/icon.png b/client/src-tauri/icons/icon.png similarity index 100% rename from notto-client/src-tauri/icons/icon.png rename to client/src-tauri/icons/icon.png diff --git a/notto-client/src-tauri/src/commands.rs b/client/src-tauri/src/commands.rs similarity index 100% rename from notto-client/src-tauri/src/commands.rs rename to client/src-tauri/src/commands.rs diff --git a/notto-client/src-tauri/src/crypt/mod.rs b/client/src-tauri/src/crypt/mod.rs similarity index 99% rename from notto-client/src-tauri/src/crypt/mod.rs rename to client/src-tauri/src/crypt/mod.rs index 594e696..5207730 100644 --- a/notto-client/src-tauri/src/crypt/mod.rs +++ b/client/src-tauri/src/crypt/mod.rs @@ -260,7 +260,7 @@ mod tests { #[test] fn encrypt_decrypt_roundtrip() { let key = random_key(); - let plaintext = b"hello, notto!"; + let plaintext = b"hello, nooto!"; let (ciphertext, nonce) = encrypt_data(plaintext, &key).unwrap(); let decrypted = decrypt_data(&ciphertext, &nonce, &key).unwrap(); diff --git a/notto-client/src-tauri/src/db/mod.rs b/client/src-tauri/src/db/mod.rs similarity index 100% rename from notto-client/src-tauri/src/db/mod.rs rename to client/src-tauri/src/db/mod.rs diff --git a/notto-client/src-tauri/src/db/operations.rs b/client/src-tauri/src/db/operations.rs similarity index 100% rename from notto-client/src-tauri/src/db/operations.rs rename to client/src-tauri/src/db/operations.rs diff --git a/notto-client/src-tauri/src/db/schema.rs b/client/src-tauri/src/db/schema.rs similarity index 100% rename from notto-client/src-tauri/src/db/schema.rs rename to client/src-tauri/src/db/schema.rs diff --git a/notto-client/src-tauri/src/lib.rs b/client/src-tauri/src/lib.rs similarity index 98% rename from notto-client/src-tauri/src/lib.rs rename to client/src-tauri/src/lib.rs index 7f783a9..7e3314d 100644 --- a/notto-client/src-tauri/src/lib.rs +++ b/client/src-tauri/src/lib.rs @@ -41,7 +41,7 @@ pub fn run() { .path() .app_data_dir() .map_err(|e| anyhow::anyhow!("Failed to get app data directory: {e}"))? - .join("notto.db"); + .join("nooto.db"); let database = db::init(db_path) .map_err(|e| anyhow::anyhow!("Failed to initialise database: {e:#}"))?; diff --git a/notto-client/src-tauri/src/main.rs b/client/src-tauri/src/main.rs similarity index 100% rename from notto-client/src-tauri/src/main.rs rename to client/src-tauri/src/main.rs diff --git a/notto-client/src-tauri/src/sync/mod.rs b/client/src-tauri/src/sync/mod.rs similarity index 100% rename from notto-client/src-tauri/src/sync/mod.rs rename to client/src-tauri/src/sync/mod.rs diff --git a/notto-client/src-tauri/src/sync/operations.rs b/client/src-tauri/src/sync/operations.rs similarity index 100% rename from notto-client/src-tauri/src/sync/operations.rs rename to client/src-tauri/src/sync/operations.rs diff --git a/notto-client/src-tauri/src/sync/service.rs b/client/src-tauri/src/sync/service.rs similarity index 100% rename from notto-client/src-tauri/src/sync/service.rs rename to client/src-tauri/src/sync/service.rs diff --git a/notto-client/src-tauri/tauri.conf.json b/client/src-tauri/tauri.conf.json similarity index 87% rename from notto-client/src-tauri/tauri.conf.json rename to client/src-tauri/tauri.conf.json index 6348554..b8de73a 100644 --- a/notto-client/src-tauri/tauri.conf.json +++ b/client/src-tauri/tauri.conf.json @@ -1,8 +1,8 @@ { "$schema": "https://schema.tauri.app/config/2", - "productName": "notto", + "productName": "nooto", "version": "0.1.0", - "identifier": "com.notto.app", + "identifier": "com.nooto.app", "build": { "beforeDevCommand": "npm run dev", "devUrl": "http://localhost:1420", @@ -12,7 +12,7 @@ "app": { "windows": [ { - "title": "notto", + "title": "nooto", "width": 800, "height": 600 } diff --git a/notto-client/src/App.css b/client/src/App.css similarity index 100% rename from notto-client/src/App.css rename to client/src/App.css diff --git a/notto-client/src/App.tsx b/client/src/App.tsx similarity index 100% rename from notto-client/src/App.tsx rename to client/src/App.tsx diff --git a/notto-client/src/assets/react.svg b/client/src/assets/react.svg similarity index 100% rename from notto-client/src/assets/react.svg rename to client/src/assets/react.svg diff --git a/notto-client/src/components/Home.tsx b/client/src/components/Home.tsx similarity index 100% rename from notto-client/src/components/Home.tsx rename to client/src/components/Home.tsx diff --git a/notto-client/src/components/Toaster.tsx b/client/src/components/Toaster.tsx similarity index 100% rename from notto-client/src/components/Toaster.tsx rename to client/src/components/Toaster.tsx diff --git a/notto-client/src/components/account/AccountMenu.tsx b/client/src/components/account/AccountMenu.tsx similarity index 100% rename from notto-client/src/components/account/AccountMenu.tsx rename to client/src/components/account/AccountMenu.tsx diff --git a/notto-client/src/components/account/AuthForm.tsx b/client/src/components/account/AuthForm.tsx similarity index 100% rename from notto-client/src/components/account/AuthForm.tsx rename to client/src/components/account/AuthForm.tsx diff --git a/notto-client/src/components/account/WorkspaceMenu.tsx b/client/src/components/account/WorkspaceMenu.tsx similarity index 100% rename from notto-client/src/components/account/WorkspaceMenu.tsx rename to client/src/components/account/WorkspaceMenu.tsx diff --git a/notto-client/src/components/icons/Icon.tsx b/client/src/components/icons/Icon.tsx similarity index 100% rename from notto-client/src/components/icons/Icon.tsx rename to client/src/components/icons/Icon.tsx diff --git a/notto-client/src/components/modals/ConflictModal.tsx b/client/src/components/modals/ConflictModal.tsx similarity index 100% rename from notto-client/src/components/modals/ConflictModal.tsx rename to client/src/components/modals/ConflictModal.tsx diff --git a/notto-client/src/components/modals/DeleteNoteConfirmModal.tsx b/client/src/components/modals/DeleteNoteConfirmModal.tsx similarity index 100% rename from notto-client/src/components/modals/DeleteNoteConfirmModal.tsx rename to client/src/components/modals/DeleteNoteConfirmModal.tsx diff --git a/notto-client/src/components/modals/LogoutWorkspaceConfirmModal.tsx b/client/src/components/modals/LogoutWorkspaceConfirmModal.tsx similarity index 100% rename from notto-client/src/components/modals/LogoutWorkspaceConfirmModal.tsx rename to client/src/components/modals/LogoutWorkspaceConfirmModal.tsx diff --git a/notto-client/src/components/note/FolderView.tsx b/client/src/components/note/FolderView.tsx similarity index 100% rename from notto-client/src/components/note/FolderView.tsx rename to client/src/components/note/FolderView.tsx diff --git a/notto-client/src/components/note/NoteEditor.css b/client/src/components/note/NoteEditor.css similarity index 100% rename from notto-client/src/components/note/NoteEditor.css rename to client/src/components/note/NoteEditor.css diff --git a/notto-client/src/components/note/NoteEditor.tsx b/client/src/components/note/NoteEditor.tsx similarity index 100% rename from notto-client/src/components/note/NoteEditor.tsx rename to client/src/components/note/NoteEditor.tsx diff --git a/notto-client/src/components/note/NoteHeader.tsx b/client/src/components/note/NoteHeader.tsx similarity index 100% rename from notto-client/src/components/note/NoteHeader.tsx rename to client/src/components/note/NoteHeader.tsx diff --git a/notto-client/src/components/sidebar/NoteTree.tsx b/client/src/components/sidebar/NoteTree.tsx similarity index 100% rename from notto-client/src/components/sidebar/NoteTree.tsx rename to client/src/components/sidebar/NoteTree.tsx diff --git a/notto-client/src/components/sidebar/Sidebar.tsx b/client/src/components/sidebar/Sidebar.tsx similarity index 99% rename from notto-client/src/components/sidebar/Sidebar.tsx rename to client/src/components/sidebar/Sidebar.tsx index 1bdb077..ceff882 100644 --- a/notto-client/src/components/sidebar/Sidebar.tsx +++ b/client/src/components/sidebar/Sidebar.tsx @@ -97,7 +97,7 @@ export default function Sidebar({ {/* Header */}
-

Notto

+

Nooto

{!showDeleted && ( <> diff --git a/notto-client/src/lib/__tests__/errors.test.ts b/client/src/lib/__tests__/errors.test.ts similarity index 100% rename from notto-client/src/lib/__tests__/errors.test.ts rename to client/src/lib/__tests__/errors.test.ts diff --git a/notto-client/src/lib/errors.ts b/client/src/lib/errors.ts similarity index 100% rename from notto-client/src/lib/errors.ts rename to client/src/lib/errors.ts diff --git a/notto-client/src/main.tsx b/client/src/main.tsx similarity index 100% rename from notto-client/src/main.tsx rename to client/src/main.tsx diff --git a/notto-client/src/store/__tests__/general.test.ts b/client/src/store/__tests__/general.test.ts similarity index 100% rename from notto-client/src/store/__tests__/general.test.ts rename to client/src/store/__tests__/general.test.ts diff --git a/notto-client/src/store/__tests__/modals.test.ts b/client/src/store/__tests__/modals.test.ts similarity index 100% rename from notto-client/src/store/__tests__/modals.test.ts rename to client/src/store/__tests__/modals.test.ts diff --git a/notto-client/src/store/__tests__/toasts.test.ts b/client/src/store/__tests__/toasts.test.ts similarity index 100% rename from notto-client/src/store/__tests__/toasts.test.ts rename to client/src/store/__tests__/toasts.test.ts diff --git a/notto-client/src/store/general.tsx b/client/src/store/general.tsx similarity index 100% rename from notto-client/src/store/general.tsx rename to client/src/store/general.tsx diff --git a/notto-client/src/store/modals.tsx b/client/src/store/modals.tsx similarity index 100% rename from notto-client/src/store/modals.tsx rename to client/src/store/modals.tsx diff --git a/notto-client/src/store/toasts.ts b/client/src/store/toasts.ts similarity index 100% rename from notto-client/src/store/toasts.ts rename to client/src/store/toasts.ts diff --git a/notto-client/src/test/setup.ts b/client/src/test/setup.ts similarity index 100% rename from notto-client/src/test/setup.ts rename to client/src/test/setup.ts diff --git a/notto-client/src/types.ts b/client/src/types.ts similarity index 100% rename from notto-client/src/types.ts rename to client/src/types.ts diff --git a/notto-client/src/vite-env.d.ts b/client/src/vite-env.d.ts similarity index 100% rename from notto-client/src/vite-env.d.ts rename to client/src/vite-env.d.ts diff --git a/notto-client/tsconfig.json b/client/tsconfig.json similarity index 100% rename from notto-client/tsconfig.json rename to client/tsconfig.json diff --git a/notto-client/tsconfig.node.json b/client/tsconfig.node.json similarity index 100% rename from notto-client/tsconfig.node.json rename to client/tsconfig.node.json diff --git a/notto-client/vite.config.ts b/client/vite.config.ts similarity index 100% rename from notto-client/vite.config.ts rename to client/vite.config.ts diff --git a/notto-client/src-tauri/gen/android/app/src/main/res/values/strings.xml b/notto-client/src-tauri/gen/android/app/src/main/res/values/strings.xml deleted file mode 100644 index 14be9e6..0000000 --- a/notto-client/src-tauri/gen/android/app/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - notto - notto - \ No newline at end of file diff --git a/notto-server/Cargo.toml b/server/Cargo.toml similarity index 94% rename from notto-server/Cargo.toml rename to server/Cargo.toml index feee1ca..10d4771 100644 --- a/notto-server/Cargo.toml +++ b/server/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "notto-server" +name = "nooto-server" version = "0.1.0" edition = "2024" diff --git a/notto-server/src/main.rs b/server/src/main.rs similarity index 100% rename from notto-server/src/main.rs rename to server/src/main.rs diff --git a/notto-server/src/schema.rs b/server/src/schema.rs similarity index 100% rename from notto-server/src/schema.rs rename to server/src/schema.rs