From 3aa16906d68566f8916b93506a5dd892497fa947 Mon Sep 17 00:00:00 2001
From: Thalia Wood <42354895+polygeist111@users.noreply.github.com>
Date: Thu, 30 Oct 2025 10:55:49 -0700
Subject: [PATCH 01/80] Add Actions linting
---
.github/workflows/format_and_lint.yml | 50 +++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
create mode 100644 .github/workflows/format_and_lint.yml
diff --git a/.github/workflows/format_and_lint.yml b/.github/workflows/format_and_lint.yml
new file mode 100644
index 000000000..03e98e6b0
--- /dev/null
+++ b/.github/workflows/format_and_lint.yml
@@ -0,0 +1,50 @@
+---
+# template source: https://github.com/bretfisher/super-linter-workflow/blob/main/templates/call-super-linter.yaml
+name: Lint Code Base
+
+on:
+ # run anytime a PR is merged to main or a direct push to main
+ push:
+ branches: [main]
+
+ # run on any push to a PR branch
+ pull_request:
+
+ # run on demand
+ workflow_dispatch:
+
+# cancel any previously-started, yet still active runs of this workflow on the same branch
+concurrency:
+ group: ${{ github.ref }}-${{ github.workflow }}
+ cancel-in-progress: true
+
+permissions: read-all
+
+# adapted from https://mskelton.medium.com/auto-formatting-code-using-prettier-and-github-actions-ed458f58b7df
+jobs:
+ call-super-linter:
+ # needs: format
+ name: Call Super-Linter
+
+ permissions:
+ contents: read # clone the repo to lint
+ statuses: write # read/write to repo custom statuses
+
+ ### use Reusable Workflows to call my workflow remotely
+ ### https://docs.github.com/en/actions/learn-github-actions/reusing-workflows
+ ### you can also call workflows from inside the same repo via file path
+
+ # FIXME: customize uri to point to your own reusable linter repository
+ uses: polygeist111/super-linter-workflow/.github/workflows/reusable-super-linter.yaml@main
+ # TODO: update url to point to gb reusable linter, not thalia's
+
+ ### Optional settings examples
+
+ with:
+ ### For a DevOps-focused repository. Prevents some code-language linters from running
+ ### defaults to false
+ # devops-only: false
+
+ ### A regex to exclude files from linting
+ ### defaults to empty
+ filter-regex-exclude: src/tarpit/raw_downloads/*
From 5f96903188c9b7efdc1a9d1a86f934b629bedb4d Mon Sep 17 00:00:00 2001
From: Thalia Wood <42354895+polygeist111@users.noreply.github.com>
Date: Thu, 30 Oct 2025 11:19:05 -0700
Subject: [PATCH 02/80] Implement pre-commit formatting with Prettier
---
.husky/_/pre-commit | 4 ++++
.prettierignore | 2 ++
package-lock.json | 45 +++++++++++++++++++++++++++++++++++++++++++++
package.json | 9 +++++++++
4 files changed, 60 insertions(+)
create mode 100755 .husky/_/pre-commit
create mode 100644 .prettierignore
create mode 100644 package-lock.json
create mode 100644 package.json
diff --git a/.husky/_/pre-commit b/.husky/_/pre-commit
new file mode 100755
index 000000000..fc7f8b24c
--- /dev/null
+++ b/.husky/_/pre-commit
@@ -0,0 +1,4 @@
+#!/usr/bin/env sh
+. "$(dirname "$0")/h"
+
+npm run format
\ No newline at end of file
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 000000000..227b71fe6
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,2 @@
+build
+coverage
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 000000000..d05483656
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,45 @@
+{
+ "name": "Project-Mesh",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "devDependencies": {
+ "husky": "^9.1.7",
+ "prettier": "^3.6.2"
+ }
+ },
+ "node_modules/husky": {
+ "version": "9.1.7",
+ "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz",
+ "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "husky": "bin.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/typicode"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
+ "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 000000000..9be7e5054
--- /dev/null
+++ b/package.json
@@ -0,0 +1,9 @@
+{
+ "scripts": {
+ "format": "prettier --write . --ignore-unknown"
+ },
+ "devDependencies": {
+ "husky": "^9.1.7",
+ "prettier": "^3.6.2"
+ }
+}
From 428e12265e68f25984195cd6c874f04c89fc957a Mon Sep 17 00:00:00 2001
From: Thalia Wood <42354895+polygeist111@users.noreply.github.com>
Date: Thu, 30 Oct 2025 11:20:33 -0700
Subject: [PATCH 03/80] Add Prettier, Super-Linter badges
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index ddb1d424c..61d8516fe 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,8 @@ New version by wil-mesh-rmit
Project Mesh runs locally on an android device. Build the project then either export the APK and send to the device, or use ADB to install. The app only works on physical devices, and not the android simulator.
+
[](https://github.com/marketplace/actions/super-linter) [](https://github.com/prettier/prettier)
+
# Deployment Instructions
The Android app runs independently of an internet connection. The APK needs to be installed in each phone, then the phones are able to connect to each other from within the app.
1. Open the app
From e5fa935d9d4b7df35867afe2c9dae231ff6d4a5c Mon Sep 17 00:00:00 2001
From: Thalia Wood <42354895+polygeist111@users.noreply.github.com>
Date: Thu, 30 Oct 2025 11:22:33 -0700
Subject: [PATCH 04/80] Reformat badges
---
README.md | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 61d8516fe..80bdd629e 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,12 @@ New version by wil-mesh-rmit
Project Mesh runs locally on an android device. Build the project then either export the APK and send to the device, or use ADB to install. The app only works on physical devices, and not the android simulator.
-[](https://github.com/marketplace/actions/super-linter) [](https://github.com/prettier/prettier)
+
+
+[](https://github.com/marketplace/actions/super-linter)
+[](https://github.com/prettier/prettier)
+
+
# Deployment Instructions
The Android app runs independently of an internet connection. The APK needs to be installed in each phone, then the phones are able to connect to each other from within the app.
From 3737c0351a700bd380d5f6e7a5d0e6feaacf2766 Mon Sep 17 00:00:00 2001
From: Thalia Wood <42354895+polygeist111@users.noreply.github.com>
Date: Thu, 30 Oct 2025 11:32:23 -0700
Subject: [PATCH 05/80] Correct badges
---
README.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 80bdd629e..1e363e466 100644
--- a/README.md
+++ b/README.md
@@ -5,12 +5,12 @@ New version by wil-mesh-rmit
Project Mesh runs locally on an android device. Build the project then either export the APK and send to the device, or use ADB to install. The app only works on physical devices, and not the android simulator.
-
+
-[](https://github.com/marketplace/actions/super-linter)
-[](https://github.com/prettier/prettier)
+
+
-
+
# Deployment Instructions
The Android app runs independently of an internet connection. The APK needs to be installed in each phone, then the phones are able to connect to each other from within the app.
From 5124610ed7647210644b4fc0a49dcd9f5e70f2e1 Mon Sep 17 00:00:00 2001
From: Thalia Wood <42354895+polygeist111@users.noreply.github.com>
Date: Thu, 30 Oct 2025 11:36:24 -0700
Subject: [PATCH 06/80] Test pre-commit Prettier action
This commit will be effectively rolled back, it's just to test Prettier in action
---
prettier_test.js | 7 +++++++
1 file changed, 7 insertions(+)
create mode 100644 prettier_test.js
diff --git a/prettier_test.js b/prettier_test.js
new file mode 100644
index 000000000..a9d6aebbc
--- /dev/null
+++ b/prettier_test.js
@@ -0,0 +1,7 @@
+const name = "James";
+const person ={first: name }
+console. log(person);
+const sayHelloLinting = (fName) => { console. log(`Hello linting, ${fName}`) }
+sayHelloLinting('James');
+// this code is not project-relevant and will be removed
+// it is simply to test that Prettier is functioning correctly as a pre-commit action
\ No newline at end of file
From e16f9ae8e3e7fce383232bf4358dda5f0b18fe2c Mon Sep 17 00:00:00 2001
From: Thalia Wood <42354895+polygeist111@users.noreply.github.com>
Date: Thu, 30 Oct 2025 11:40:42 -0700
Subject: [PATCH 07/80] Debug Prettier pre-commit (#1)
Add back husky install script in package.json
---
package.json | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 9be7e5054..def90ffdb 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,7 @@
{
"scripts": {
- "format": "prettier --write . --ignore-unknown"
+ "format": "prettier --write . --ignore-unknown",
+ "prepare": "husky install"
},
"devDependencies": {
"husky": "^9.1.7",
From a45ebec4b8c032df86d0d504ecb9c4ad194c3ee3 Mon Sep 17 00:00:00 2001
From: Thalia Wood <42354895+polygeist111@users.noreply.github.com>
Date: Thu, 30 Oct 2025 11:51:51 -0700
Subject: [PATCH 08/80] Debug Prettier pre-commit (#2)
---
.husky/.gitignore | 1 +
.husky/pre-commit | 4 ++++
2 files changed, 5 insertions(+)
create mode 100644 .husky/.gitignore
create mode 100755 .husky/pre-commit
diff --git a/.husky/.gitignore b/.husky/.gitignore
new file mode 100644
index 000000000..c9cdc63b0
--- /dev/null
+++ b/.husky/.gitignore
@@ -0,0 +1 @@
+_
\ No newline at end of file
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100755
index 000000000..fe0f899a1
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1,4 @@
+#!/usr/bin/env sh
+. "$(dirname "$0")/_/h"
+
+npm run format
\ No newline at end of file
From ef08187b9e2954e2280ef708011eafc7f2744a7c Mon Sep 17 00:00:00 2001
From: Thalia Wood <42354895+polygeist111@users.noreply.github.com>
Date: Thu, 30 Oct 2025 11:58:17 -0700
Subject: [PATCH 09/80] Debug Prettier pre-commit (#3)
Add back lint-staged
---
.husky/_/pre-commit | 4 -
.husky/pre-commit | 2 +-
package-lock.json | 489 ++++++++++++++++++++++++++++++++++++++++++++
package.json | 4 +
4 files changed, 494 insertions(+), 5 deletions(-)
delete mode 100755 .husky/_/pre-commit
diff --git a/.husky/_/pre-commit b/.husky/_/pre-commit
deleted file mode 100755
index fc7f8b24c..000000000
--- a/.husky/_/pre-commit
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/usr/bin/env sh
-. "$(dirname "$0")/h"
-
-npm run format
\ No newline at end of file
diff --git a/.husky/pre-commit b/.husky/pre-commit
index fe0f899a1..f8d714904 100755
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1,4 +1,4 @@
#!/usr/bin/env sh
. "$(dirname "$0")/_/h"
-npm run format
\ No newline at end of file
+npx lint-staged
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index d05483656..1752a2326 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6,9 +6,168 @@
"": {
"devDependencies": {
"husky": "^9.1.7",
+ "lint-staged": "^16.2.6",
"prettier": "^3.6.2"
}
},
+ "node_modules/ansi-escapes": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.1.1.tgz",
+ "integrity": "sha512-Zhl0ErHcSRUaVfGUeUdDuLgpkEo8KIFjB4Y9uAc46ScOpdDiU1Dbyplh7qWJeJ/ZHpbyMSM26+X3BySgnIz40Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "environment": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
+ "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cli-cursor": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz",
+ "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "restore-cursor": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-truncate": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.1.1.tgz",
+ "integrity": "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "slice-ansi": "^7.1.0",
+ "string-width": "^8.0.0"
+ },
+ "engines": {
+ "node": ">=20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/colorette": {
+ "version": "2.0.20",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
+ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/commander": {
+ "version": "14.0.2",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz",
+ "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz",
+ "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/environment": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz",
+ "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eventemitter3": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
+ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/get-east-asian-width": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz",
+ "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/husky": {
"version": "9.1.7",
"resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz",
@@ -25,6 +184,177 @@
"url": "https://github.com/sponsors/typicode"
}
},
+ "node_modules/is-fullwidth-code-point": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz",
+ "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-east-asian-width": "^1.3.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/lint-staged": {
+ "version": "16.2.6",
+ "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.2.6.tgz",
+ "integrity": "sha512-s1gphtDbV4bmW1eylXpVMk2u7is7YsrLl8hzrtvC70h4ByhcMLZFY01Fx05ZUDNuv1H8HO4E+e2zgejV1jVwNw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "commander": "^14.0.1",
+ "listr2": "^9.0.5",
+ "micromatch": "^4.0.8",
+ "nano-spawn": "^2.0.0",
+ "pidtree": "^0.6.0",
+ "string-argv": "^0.3.2",
+ "yaml": "^2.8.1"
+ },
+ "bin": {
+ "lint-staged": "bin/lint-staged.js"
+ },
+ "engines": {
+ "node": ">=20.17"
+ },
+ "funding": {
+ "url": "https://opencollective.com/lint-staged"
+ }
+ },
+ "node_modules/listr2": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz",
+ "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cli-truncate": "^5.0.0",
+ "colorette": "^2.0.20",
+ "eventemitter3": "^5.0.1",
+ "log-update": "^6.1.0",
+ "rfdc": "^1.4.1",
+ "wrap-ansi": "^9.0.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/log-update": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz",
+ "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-escapes": "^7.0.0",
+ "cli-cursor": "^5.0.0",
+ "slice-ansi": "^7.1.0",
+ "strip-ansi": "^7.1.0",
+ "wrap-ansi": "^9.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mimic-function": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz",
+ "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/nano-spawn": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/nano-spawn/-/nano-spawn-2.0.0.tgz",
+ "integrity": "sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.17"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/nano-spawn?sponsor=1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz",
+ "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-function": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pidtree": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz",
+ "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "pidtree": "bin/pidtree.js"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
"node_modules/prettier": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
@@ -40,6 +370,165 @@
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
+ },
+ "node_modules/restore-cursor": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz",
+ "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "onetime": "^7.0.0",
+ "signal-exit": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/rfdc": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
+ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/slice-ansi": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz",
+ "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.2.1",
+ "is-fullwidth-code-point": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ }
+ },
+ "node_modules/string-argv": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz",
+ "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6.19"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz",
+ "integrity": "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-east-asian-width": "^1.3.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz",
+ "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz",
+ "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.2.1",
+ "string-width": "^7.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/string-width": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+ "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^10.3.0",
+ "get-east-asian-width": "^1.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yaml": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz",
+ "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ }
}
}
}
diff --git a/package.json b/package.json
index def90ffdb..cc2f6955a 100644
--- a/package.json
+++ b/package.json
@@ -3,8 +3,12 @@
"format": "prettier --write . --ignore-unknown",
"prepare": "husky install"
},
+ "lint-staged": {
+ "*": "prettier --write -- ignore-unknown"
+ },
"devDependencies": {
"husky": "^9.1.7",
+ "lint-staged": "^16.2.6",
"prettier": "^3.6.2"
}
}
From bcba2cda39eaf9704a4d326f3f11bcb626bece2d Mon Sep 17 00:00:00 2001
From: Thalia Wood <42354895+polygeist111@users.noreply.github.com>
Date: Thu, 30 Oct 2025 12:02:20 -0700
Subject: [PATCH 10/80] Test Prettier pre-commit (#4)
---
prettier_test.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/prettier_test.js b/prettier_test.js
index a9d6aebbc..4ec3c6f83 100644
--- a/prettier_test.js
+++ b/prettier_test.js
@@ -4,4 +4,5 @@ console. log(person);
const sayHelloLinting = (fName) => { console. log(`Hello linting, ${fName}`) }
sayHelloLinting('James');
// this code is not project-relevant and will be removed
-// it is simply to test that Prettier is functioning correctly as a pre-commit action
\ No newline at end of file
+// it is simply to test that Prettier is functioning correctly as a pre-commit action
+// adding change to stage
\ No newline at end of file
From 8b09517ff4e049c03a76ac9967a7dc80ca28f684 Mon Sep 17 00:00:00 2001
From: Thalia Wood <42354895+polygeist111@users.noreply.github.com>
Date: Thu, 30 Oct 2025 12:24:44 -0700
Subject: [PATCH 11/80] Debug Prettier pre-commit (#5)
---
.husky/.gitignore | 6 +++++-
.husky/pre-commit | 4 ----
package.json | 2 +-
prettier_test.js | 2 +-
4 files changed, 7 insertions(+), 7 deletions(-)
delete mode 100755 .husky/pre-commit
diff --git a/.husky/.gitignore b/.husky/.gitignore
index c9cdc63b0..7d11b16d7 100644
--- a/.husky/.gitignore
+++ b/.husky/.gitignore
@@ -1 +1,5 @@
-_
\ No newline at end of file
+# Ignore these
+_
+
+# But not these
+!_/pre-commit
\ No newline at end of file
diff --git a/.husky/pre-commit b/.husky/pre-commit
deleted file mode 100755
index f8d714904..000000000
--- a/.husky/pre-commit
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/usr/bin/env sh
-. "$(dirname "$0")/_/h"
-
-npx lint-staged
\ No newline at end of file
diff --git a/package.json b/package.json
index cc2f6955a..9abb9ee0b 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
"prepare": "husky install"
},
"lint-staged": {
- "*": "prettier --write -- ignore-unknown"
+ "*": "prettier --write --ignore-unknown"
},
"devDependencies": {
"husky": "^9.1.7",
diff --git a/prettier_test.js b/prettier_test.js
index 4ec3c6f83..44f6ffb42 100644
--- a/prettier_test.js
+++ b/prettier_test.js
@@ -5,4 +5,4 @@ const sayHelloLinting = (fName) => { console. log(`Hello linting, ${fName}`) }
sayHelloLinting('James');
// this code is not project-relevant and will be removed
// it is simply to test that Prettier is functioning correctly as a pre-commit action
-// adding change to stage
\ No newline at end of file
+// adding change to stage :)
\ No newline at end of file
From 7cdabd99485b6ea856e6decc723e97fde12d52cd Mon Sep 17 00:00:00 2001
From: Thalia Wood <42354895+polygeist111@users.noreply.github.com>
Date: Thu, 30 Oct 2025 12:28:50 -0700
Subject: [PATCH 12/80] Debug Prettier pre-commit (#6)
---
package.json | 5 +++--
prettier_test.js | 2 +-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/package.json b/package.json
index 9abb9ee0b..d5c09f1fb 100644
--- a/package.json
+++ b/package.json
@@ -1,10 +1,11 @@
{
"scripts": {
"format": "prettier --write . --ignore-unknown",
- "prepare": "husky install"
+ "prepare": "husky install",
+ "lint-staged": "npx lint-staged"
},
"lint-staged": {
- "*": "prettier --write --ignore-unknown"
+ "**/*": "prettier --write .--ignore-unknown"
},
"devDependencies": {
"husky": "^9.1.7",
diff --git a/prettier_test.js b/prettier_test.js
index 44f6ffb42..5b30be991 100644
--- a/prettier_test.js
+++ b/prettier_test.js
@@ -5,4 +5,4 @@ const sayHelloLinting = (fName) => { console. log(`Hello linting, ${fName}`) }
sayHelloLinting('James');
// this code is not project-relevant and will be removed
// it is simply to test that Prettier is functioning correctly as a pre-commit action
-// adding change to stage :)
\ No newline at end of file
+// adding change to stage :3
\ No newline at end of file
From 38db27c3f8df25481586fa337b317e7478b46366 Mon Sep 17 00:00:00 2001
From: Thalia Wood <42354895+polygeist111@users.noreply.github.com>
Date: Thu, 30 Oct 2025 13:02:52 -0700
Subject: [PATCH 13/80] Debug Prettier pre-commit (#7)
---
.husky/.gitignore | 5 -----
.husky/_/pre-commit | 4 ++++
package.json | 2 +-
prettier_test.js | 2 +-
4 files changed, 6 insertions(+), 7 deletions(-)
delete mode 100644 .husky/.gitignore
create mode 100755 .husky/_/pre-commit
diff --git a/.husky/.gitignore b/.husky/.gitignore
deleted file mode 100644
index 7d11b16d7..000000000
--- a/.husky/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-# Ignore these
-_
-
-# But not these
-!_/pre-commit
\ No newline at end of file
diff --git a/.husky/_/pre-commit b/.husky/_/pre-commit
new file mode 100755
index 000000000..656260e02
--- /dev/null
+++ b/.husky/_/pre-commit
@@ -0,0 +1,4 @@
+#!/usr/bin/env sh
+. "$(dirname "$0")/h"
+
+npm run lint-staged
\ No newline at end of file
diff --git a/package.json b/package.json
index d5c09f1fb..d219f17c5 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"scripts": {
"format": "prettier --write . --ignore-unknown",
"prepare": "husky install",
- "lint-staged": "npx lint-staged"
+ "lint-staged": "lint-staged"
},
"lint-staged": {
"**/*": "prettier --write .--ignore-unknown"
diff --git a/prettier_test.js b/prettier_test.js
index 5b30be991..44f6ffb42 100644
--- a/prettier_test.js
+++ b/prettier_test.js
@@ -5,4 +5,4 @@ const sayHelloLinting = (fName) => { console. log(`Hello linting, ${fName}`) }
sayHelloLinting('James');
// this code is not project-relevant and will be removed
// it is simply to test that Prettier is functioning correctly as a pre-commit action
-// adding change to stage :3
\ No newline at end of file
+// adding change to stage :)
\ No newline at end of file
From 3011ce0a0df59b2436d6270721c65f1795b5b333 Mon Sep 17 00:00:00 2001
From: Thalia Wood <42354895+polygeist111@users.noreply.github.com>
Date: Thu, 30 Oct 2025 13:07:32 -0700
Subject: [PATCH 14/80] Debug Prettier pre-commit (#8)
---
package.json | 2 +-
prettier_test.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/package.json b/package.json
index d219f17c5..b970383f3 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
"lint-staged": "lint-staged"
},
"lint-staged": {
- "**/*": "prettier --write .--ignore-unknown"
+ "**/*": "prettier --write .--ignore-unknown && echo 'Formatting a file :3'"
},
"devDependencies": {
"husky": "^9.1.7",
diff --git a/prettier_test.js b/prettier_test.js
index 44f6ffb42..5b30be991 100644
--- a/prettier_test.js
+++ b/prettier_test.js
@@ -5,4 +5,4 @@ const sayHelloLinting = (fName) => { console. log(`Hello linting, ${fName}`) }
sayHelloLinting('James');
// this code is not project-relevant and will be removed
// it is simply to test that Prettier is functioning correctly as a pre-commit action
-// adding change to stage :)
\ No newline at end of file
+// adding change to stage :3
\ No newline at end of file
From 909d253c38abf6c95f3101e512f6454d9361ed93 Mon Sep 17 00:00:00 2001
From: Thalia Wood <42354895+polygeist111@users.noreply.github.com>
Date: Thu, 30 Oct 2025 13:12:55 -0700
Subject: [PATCH 15/80] Debug Prettier pre-commit (#9)
---
.husky/_/pre-commit | 4 ----
.husky/pre-commit | 1 +
.prettierignore | 3 ++-
package.json | 4 ++--
prettier_test.js | 12 +++++++-----
5 files changed, 12 insertions(+), 12 deletions(-)
delete mode 100755 .husky/_/pre-commit
create mode 100644 .husky/pre-commit
diff --git a/.husky/_/pre-commit b/.husky/_/pre-commit
deleted file mode 100755
index 656260e02..000000000
--- a/.husky/_/pre-commit
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/usr/bin/env sh
-. "$(dirname "$0")/h"
-
-npm run lint-staged
\ No newline at end of file
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100644
index 000000000..0100eae14
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1 @@
+npm run lint-staged
diff --git a/.prettierignore b/.prettierignore
index 227b71fe6..00543e568 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,2 +1,3 @@
build
-coverage
\ No newline at end of file
+coverage
+node_modules
\ No newline at end of file
diff --git a/package.json b/package.json
index b970383f3..971f31cbe 100644
--- a/package.json
+++ b/package.json
@@ -1,11 +1,11 @@
{
"scripts": {
"format": "prettier --write . --ignore-unknown",
- "prepare": "husky install",
+ "prepare": "husky",
"lint-staged": "lint-staged"
},
"lint-staged": {
- "**/*": "prettier --write .--ignore-unknown && echo 'Formatting a file :3'"
+ "**/*": "prettier --write . --ignore-unknown"
},
"devDependencies": {
"husky": "^9.1.7",
diff --git a/prettier_test.js b/prettier_test.js
index 5b30be991..a692bc0bc 100644
--- a/prettier_test.js
+++ b/prettier_test.js
@@ -1,8 +1,10 @@
const name = "James";
-const person ={first: name }
-console. log(person);
-const sayHelloLinting = (fName) => { console. log(`Hello linting, ${fName}`) }
-sayHelloLinting('James');
+const person = { first: name };
+console.log(person);
+const sayHelloLinting = (fName) => {
+ console.log(`Hello linting, ${fName}`);
+};
+sayHelloLinting("James");
// this code is not project-relevant and will be removed
// it is simply to test that Prettier is functioning correctly as a pre-commit action
-// adding change to stage :3
\ No newline at end of file
+// adding change to stage :)
From a49d74424ef542aed2c8cdb3359939f1ef00ff96 Mon Sep 17 00:00:00 2001
From: Thalia Wood <42354895+polygeist111@users.noreply.github.com>
Date: Thu, 30 Oct 2025 13:16:24 -0700
Subject: [PATCH 16/80] Test Prettier pre-commit (#10)
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 971f31cbe..e3d1f9660 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
"lint-staged": "lint-staged"
},
"lint-staged": {
- "**/*": "prettier --write . --ignore-unknown"
+ "**/*": "prettier --write --ignore-unknown"
},
"devDependencies": {
"husky": "^9.1.7",
From 537913ed4759334b5d533cc98bd0cbbdbf796808 Mon Sep 17 00:00:00 2001
From: Thalia Wood <42354895+polygeist111@users.noreply.github.com>
Date: Thu, 30 Oct 2025 14:03:04 -0700
Subject: [PATCH 17/80] Finish Prettier Config
Add xml formatting, remove JS test file.
Tested use of Prettier Kotlin plugin, but it's ill-maintained and errors on many files so will try to use ktlint to handle kotlin formatting
---
.github/workflows/format_and_lint.yml | 2 +-
ci_readme.txt | 4 +++
package-lock.json | 41 +++++++++++++++++++++++++++
package.json | 8 +++++-
prettier_test.js | 10 -------
5 files changed, 53 insertions(+), 12 deletions(-)
create mode 100644 ci_readme.txt
delete mode 100644 prettier_test.js
diff --git a/.github/workflows/format_and_lint.yml b/.github/workflows/format_and_lint.yml
index 03e98e6b0..5c5d20e5b 100644
--- a/.github/workflows/format_and_lint.yml
+++ b/.github/workflows/format_and_lint.yml
@@ -37,7 +37,7 @@ jobs:
# FIXME: customize uri to point to your own reusable linter repository
uses: polygeist111/super-linter-workflow/.github/workflows/reusable-super-linter.yaml@main
# TODO: update url to point to gb reusable linter, not thalia's
-
+
### Optional settings examples
with:
diff --git a/ci_readme.txt b/ci_readme.txt
new file mode 100644
index 000000000..6e4c58969
--- /dev/null
+++ b/ci_readme.txt
@@ -0,0 +1,4 @@
+The CI pipeline behaves as follows:
+1. run Prettier on web-related filetypes, as well as XML
+ a. Do not use prettier-plugin-kotlin, it is not maintained and errors regularly
+2. On push, run super-linter. For all possible cases, run autofix (this covers Kotlin)
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 1752a2326..69db7e3bf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,11 +5,35 @@
"packages": {
"": {
"devDependencies": {
+ "@prettier/plugin-xml": "^3.4.2",
"husky": "^9.1.7",
"lint-staged": "^16.2.6",
"prettier": "^3.6.2"
}
},
+ "node_modules/@prettier/plugin-xml": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/@prettier/plugin-xml/-/plugin-xml-3.4.2.tgz",
+ "integrity": "sha512-/UyNlHfkuLXG6Ed85KB0WBF283xn2yavR+UtRibBRUcvEJId2DSLdGXwJ/cDa1X++SWDPzq3+GSFniHjkNy7yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@xml-tools/parser": "^1.0.11"
+ },
+ "peerDependencies": {
+ "prettier": "^3.0.0"
+ }
+ },
+ "node_modules/@xml-tools/parser": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@xml-tools/parser/-/parser-1.0.11.tgz",
+ "integrity": "sha512-aKqQ077XnR+oQtHJlrAflaZaL7qZsulWc/i/ZEooar5JiWj1eLt0+Wg28cpa+XLney107wXqneC+oG1IZvxkTA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "chevrotain": "7.1.1"
+ }
+ },
"node_modules/ansi-escapes": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.1.1.tgz",
@@ -65,6 +89,16 @@
"node": ">=8"
}
},
+ "node_modules/chevrotain": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-7.1.1.tgz",
+ "integrity": "sha512-wy3mC1x4ye+O+QkEinVJkPf5u2vsrDIYW9G7ZuwFl6v/Yu0LwUuT2POsb+NUWApebyxfkQq6+yDfRExbnI5rcw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "regexp-to-ast": "0.5.0"
+ }
+ },
"node_modules/cli-cursor": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz",
@@ -371,6 +405,13 @@
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
+ "node_modules/regexp-to-ast": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz",
+ "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/restore-cursor": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz",
diff --git a/package.json b/package.json
index e3d1f9660..163121483 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,12 @@
"devDependencies": {
"husky": "^9.1.7",
"lint-staged": "^16.2.6",
- "prettier": "^3.6.2"
+ "prettier": "^3.6.2",
+ "@prettier/plugin-xml": "^3.4.2"
+ },
+ "prettier": {
+ "plugins": [
+ "@prettier/plugin-xml"
+ ]
}
}
diff --git a/prettier_test.js b/prettier_test.js
deleted file mode 100644
index a692bc0bc..000000000
--- a/prettier_test.js
+++ /dev/null
@@ -1,10 +0,0 @@
-const name = "James";
-const person = { first: name };
-console.log(person);
-const sayHelloLinting = (fName) => {
- console.log(`Hello linting, ${fName}`);
-};
-sayHelloLinting("James");
-// this code is not project-relevant and will be removed
-// it is simply to test that Prettier is functioning correctly as a pre-commit action
-// adding change to stage :)
From 6df090beb33f70a508576e043bc2526113318249 Mon Sep 17 00:00:00 2001
From: Thalia Wood <42354895+polygeist111@users.noreply.github.com>
Date: Thu, 30 Oct 2025 14:07:21 -0700
Subject: [PATCH 18/80] Format all XML and README files
---
README.md | 13 +-
app/src/main/AndroidManifest.xml | 94 +++++----
.../greybox/projectmesh/messaging/README.md | 183 ++++++++++++------
.../com/greybox/projectmesh/testing/README.md | 73 ++++---
.../com/greybox/projectmesh/user/README.md | 71 ++++---
.../res/drawable/ic_launcher_background.xml | 37 ++--
.../res/drawable/ic_launcher_foreground.xml | 120 +++++++-----
app/src/main/res/drawable/splash_screen.xml | 10 +-
.../main/res/layout/activity_crash_screen.xml | 33 ++--
app/src/main/res/layout/activity_main.xml | 34 ++--
.../main/res/mipmap-anydpi/ic_launcher.xml | 4 +-
.../res/mipmap-anydpi/ic_launcher_round.xml | 4 +-
app/src/main/res/values-cn/strings.xml | 12 +-
app/src/main/res/values-es/strings.xml | 28 ++-
app/src/main/res/values-fr-rCA/strings.xml | 32 ++-
app/src/main/res/values-night/styles.xml | 2 +-
app/src/main/res/values/attrs_main_view.xml | 2 +-
app/src/main/res/values/colors.xml | 4 +-
app/src/main/res/values/strings.xml | 18 +-
app/src/main/res/values/styles.xml | 2 +-
app/src/main/res/values/themes.xml | 10 +-
app/src/main/res/xml/backup_rules.xml | 5 +-
.../main/res/xml/data_extraction_rules.xml | 5 +-
app/src/main/res/xml/filepaths.xml | 6 +-
24 files changed, 493 insertions(+), 309 deletions(-)
diff --git a/README.md b/README.md
index 1e363e466..9fc333137 100644
--- a/README.md
+++ b/README.md
@@ -1,26 +1,29 @@
# Project Mesh
--------------------
+
+---
+
Grey-box.ca
New version by wil-mesh-rmit
-Project Mesh runs locally on an android device. Build the project then either export the APK and send to the device, or use ADB to install. The app only works on physical devices, and not the android simulator.
+Project Mesh runs locally on an android device. Build the project then either export the APK and send to the device, or use ADB to install. The app only works on physical devices, and not the android simulator.


-
+
# Deployment Instructions
-The Android app runs independently of an internet connection. The APK needs to be installed in each phone, then the phones are able to connect to each other from within the app.
+
+The Android app runs independently of an internet connection. The APK needs to be installed in each phone, then the phones are able to connect to each other from within the app.
+
1. Open the app
2. When prompted, allow location and nearby devices permissions
3. Wait for a QR code to appear on screen
4. On each phone, use the ‘Scan QR code’ button to scan the codes of adjacent devices
5. Messages are able to be sent to connected devices with the ‘Send’ button and ‘Message’ text box
-
Credential info: N/A
GitHub URL: https://github.com/grey-box/Project-Mesh
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a5ed25801..8039c6669 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,6 +1,8 @@
-
-
+
+
@@ -24,24 +26,27 @@
+ android:name="android.hardware.camera"
+ android:required="false"
+ />
-
-
+ android:name="android.permission.NEARBY_WIFI_DEVICES"
+ android:usesPermissionFlags="neverForLocation"
+ />
+
+
-
+
-
+
@@ -55,26 +60,28 @@
+ android:name=".GlobalApp"
+ android:allowBackup="true"
+ android:dataExtractionRules="@xml/data_extraction_rules"
+ android:fullBackupContent="@xml/backup_rules"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:usesCleartextTraffic="true"
+ android:roundIcon="@mipmap/ic_launcher_round"
+ android:supportsRtl="true"
+ android:theme="@style/Theme.AppCompat"
+ android:hardwareAccelerated="true"
+ tools:targetApi="31"
+ >
+ android:name=".MainActivity"
+ android:exported="true"
+ android:label="@string/app_name"
+ android:theme="@style/Theme.ProjectMesh.Launcher"
+ >
@@ -82,21 +89,28 @@
+ android:name="androidx.core.content.FileProvider"
+ android:authorities="com.greybox.projectmesh.fileprovider"
+ android:grantUriPermissions="true"
+ android:exported="false"
+ >
+ android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/filepaths"
+ />
-
+ android:name="com.journeyapps.barcodescanner.CaptureActivity"
+ android:screenOrientation="portrait"
+ android:stateNotNeeded="true"
+ tools:replace="android:screenOrientation"
+ />
+
-
\ No newline at end of file
+
diff --git a/app/src/main/java/com/greybox/projectmesh/messaging/README.md b/app/src/main/java/com/greybox/projectmesh/messaging/README.md
index 120b26d98..d8f361889 100644
--- a/app/src/main/java/com/greybox/projectmesh/messaging/README.md
+++ b/app/src/main/java/com/greybox/projectmesh/messaging/README.md
@@ -1,9 +1,11 @@
# Messaging Module Documentation
## Overview
+
The messaging module is a core component of Project Mesh that enables peer-to-peer text communications between devices on the local mesh network. It provides a structured architecture for sending, receiving, storing, and displaying messages without requiring internet connectivity.
## Package Structure
+
```
messaging/
├── data/ # Data layer (entities and DAOs)
@@ -16,11 +18,14 @@ messaging/
├── screens/ # Composable UI screens
└── viewmodels/# View state management
```
-## Core Components
-### 1. Data Models
-#### Message Entity
-```Kotlin
+## Core Components
+
+### 1. Data Models
+
+#### Message Entity
+
+```Kotlin
@Serializable
@Entity(tableName = "message")
data class Message(
@@ -32,8 +37,10 @@ data class Message(
@ColumnInfo(name= "file") val file: URI? = null
)
```
+
#### Conversation Entity
-```Kotlin
+
+```Kotlin
@Entity(tableName = "conversations")
data class Conversation(
@PrimaryKey val id: String, // Composite ID of the two users
@@ -46,44 +53,63 @@ data class Conversation(
@ColumnInfo(name = "is_online") val isOnline: Boolean = false // Online status
)
```
+
### 2. Repositories
+
#### MessageRepository
+
Manages message data operations, including retrieving and storing messages.
+
#### ConversationRepository
+
Manages conversation data, including creating and updating conversations, tracking user statuses, and managing unread messages.
+
### 3. Network Components
+
#### MessageNetworkHandler
- Handles network communication for sending and receiving messages using HTTP requests.
+
+Handles network communication for sending and receiving messages using HTTP requests.
+
### 4. UI Components
+
#### ChatScreen
- Displays messages in a conversation and provides UI controls for sending new messages.
+
+Displays messages in a conversation and provides UI controls for sending new messages.
+
#### ConversationsHomeScreen
- Displays a list of all conversations with status indicators and message previews.
+
+Displays a list of all conversations with status indicators and message previews.
## Architecture and Data Flow
+
### Message Flow
#### 1. User Sends Message:
-* User enters text in ChatScreen and taps Send
-* ChatScreenViewModel processes the input
-* Message is first saved locally in the database
-* MessageNetworkHandler sends the message to recipient via HTTP
+
+- User enters text in ChatScreen and taps Send
+- ChatScreenViewModel processes the input
+- Message is first saved locally in the database
+- MessageNetworkHandler sends the message to recipient via HTTP
+
#### 2. Message Reception:
-* AppServer receives HTTP request on /chat endpoint
-* MessageNetworkHandler processes the incoming message
-* Message is stored in local database
-* ConversationRepository updates the conversation
-* UI is updated via StateFlow collection
+
+- AppServer receives HTTP request on /chat endpoint
+- MessageNetworkHandler processes the incoming message
+- Message is stored in local database
+- ConversationRepository updates the conversation
+- UI is updated via StateFlow collection
### Integration with Project Mesh Components
+
#### Network Integration
+
Messages are transmitted over the mesh network created by the Meshrabiya library. The system uses:
1. `AppServer`: Provides HTTP endpoints for receiving messages and handles file transfers.
2. `DeviceStatusManager`: Tracks online/offline status of devices to determine message deliverability.
3. `AndroidVirtualNode`: Manages the underlying mesh network connections.
-```kotlin
+```kotlin
// In AppServer.kt
// Handles incoming chat messages
else if(path.startsWith("/chat")) {
@@ -91,24 +117,26 @@ else if(path.startsWith("/chat")) {
val chatMessage = deserialzedJSON.content
val time = deserialzedJSON.dateReceived
val senderIp = deserialzedJSON.sender
-
+
// Handle message via MessageNetworkHandler
val message = MessageNetworkHandler.handleIncomingMessage(
chatMessage, time, senderIp, incomingfile
)
-
+
// Save to database
db.messageDao().addMessage(message)
}
```
-#### User System Integration
+#### User System Integration
+
Messages and conversations are linked to user profiles:
+
1. Each message contains a sender field with the username
2. Conversations use a composite ID created from the UUIDs of both participants
3. Online status is synchronized with the DeviceStatusManager
-```kotlin
+```kotlin
// In ConversationUtils.kt
fun createConversationId(uuid1: String, uuid2: String): String {
// Sort UUIDs to ensure consistent IDs regardless of sender/receiver
@@ -117,15 +145,21 @@ fun createConversationId(uuid1: String, uuid2: String): String {
```
#### Database Integration
+
The messaging module uses Room database for persistence:
+
1. **MeshDatabase**: Central database that contains tables for:
-* `messages`: Stores all message content
-* `conversations`: Stores conversation metadata
-* `users`: Stores user profile information
+
+- `messages`: Stores all message content
+- `conversations`: Stores conversation metadata
+- `users`: Stores user profile information
+
2. Relationship Flow:
-* Users have multiple Conversations
-* Conversations contain multiple Messages
-* Messages reference their Conversation via the chat field
+
+- Users have multiple Conversations
+- Conversations contain multiple Messages
+- Messages reference their Conversation via the chat field
+
```kotlin
// In MeshDatabase.kt
@Database(
@@ -143,35 +177,43 @@ abstract class MeshDatabase : RoomDatabase() {
abstract fun conversationDao(): ConversationDao
}
```
+
## Special Features
+
### Offline Messaging
+
1. Messages are always stored locally first
2. If recipient is offline, message remains in local database
3. UI indicates delivery status based on device connectivity
4. Messages appear in conversation history regardless of delivery status
+
### Test Device Integration
+
Special handling for test devices that simulate real users:
-* Online test device automatically responds with echo messages
-* Offline test device stores messages locally but never receives them
+
+- Online test device automatically responds with echo messages
+- Offline test device stores messages locally but never receives them
### File Attachments
+
1. Messages can include file URI attachments
2. Files are transferred separately using the file transfer system
3. Messages with attachments display file indicators in the UI
-### Usage Example
-#### Conversations Screen:
+### Usage Example
+
+#### Conversations Screen:
-* Online and Offline Users Appear With Appropriate Read Receipts from Built-in Sample Messages
-* Connected device appears in the Conversation Screen
+- Online and Offline Users Appear With Appropriate Read Receipts from Built-in Sample Messages
+- Connected device appears in the Conversation Screen
-#### Chat Screen Initial Impressions
+#### Chat Screen Initial Impressions
-* When chatting for the first time a prompt appears to start a chat
+- When chatting for the first time a prompt appears to start a chat
#### Sending A Message
@@ -184,7 +226,7 @@ Special handling for test devices that simulate real users:
fun sendChatMessage(virtualAddress: InetAddress, message: String, file: URI?) {
val sendTime = System.currentTimeMillis()
val isOnline = DeviceStatusManager.isDeviceOnline(ipAddress)
-
+
// Create message entity
val messageEntity = Message(
id = 0,
@@ -194,17 +236,17 @@ fun sendChatMessage(virtualAddress: InetAddress, message: String, file: URI?) {
chat = chatName,
file = file
)
-
+
viewModelScope.launch {
// Save to local database
db.messageDao().addMessage(messageEntity)
-
+
// Update conversation
conversationRepository.updateWithMessage(
conversationId = conversation.id,
message = messageEntity
)
-
+
// Send message if recipient is online
if (isOnline) {
appServer.sendChatMessageWithStatus(
@@ -214,11 +256,12 @@ fun sendChatMessage(virtualAddress: InetAddress, message: String, file: URI?) {
}
}
```
-#### Receiving and Displaying Messages
+
+#### Receiving and Displaying Messages
**Example**: Bob Recieves Message From Alice
-1. Conversation is Updated and Read Receipt is shown:
+1. Conversation is Updated and Read Receipt is shown:
@@ -226,7 +269,7 @@ fun sendChatMessage(virtualAddress: InetAddress, message: String, file: URI?) {
-3. When Going back to the Chat Screen Read Status is Updated:
+3. When Going back to the Chat Screen Read Status is Updated:
@@ -243,45 +286,57 @@ init {
}
}
```
+
## Best Practices
+
### 1. Consider Network Conditions:
-* Always check device online status before sending
-* Provide clear UI feedback for undelivered messages
-* Handle intermittent connectivity gracefully
+
+- Always check device online status before sending
+- Provide clear UI feedback for undelivered messages
+- Handle intermittent connectivity gracefully
### 2. Database Operations:
-* Perform all database operations on IO dispatchers
-* Use Room's Flow API for reactive UI updates
-* Keep transactions atomic to prevent data corruption
+
+- Perform all database operations on IO dispatchers
+- Use Room's Flow API for reactive UI updates
+- Keep transactions atomic to prevent data corruption
### 3. User Experience:
-* Show clear online/offline indicators
-* Provide delivery status for messages
-* Update conversation timestamps and previews promptly
+
+- Show clear online/offline indicators
+- Provide delivery status for messages
+- Update conversation timestamps and previews promptly
### 4. Security Considerations:
-* Validate message content before processing
-* Use proper JSON schema validation for incoming messages
-* Sanitize user input to prevent injection attacks
+
+- Validate message content before processing
+- Use proper JSON schema validation for incoming messages
+- Sanitize user input to prevent injection attacks
## Troubleshooting
+
### Common Issues
+
#### 1. Messages Not Sending:
-* Check device status in DeviceStatusManager
-* Verify network connectivity between devices
-* Confirm AppServer is running on both devices
+
+- Check device status in DeviceStatusManager
+- Verify network connectivity between devices
+- Confirm AppServer is running on both devices
#### 2. Missing Conversations:
-* Ensure user profile exchange was successful
-* Check conversation ID generation is consistent
-* Verify database migrations have completed
+
+- Ensure user profile exchange was successful
+- Check conversation ID generation is consistent
+- Verify database migrations have completed
#### 3. UI Not Updating:
-* Confirm StateFlow collection is active
-* Check database queries are properly observed
-* Verify Composable recomposition triggers
+
+- Confirm StateFlow collection is active
+- Check database queries are properly observed
+- Verify Composable recomposition triggers
## Future Enhancements
+
1. **Message Encryption**: Add end-to-end encryption for message content
2. **Message Status**: Add read receipts and delivery confirmations
3. **Rich Media**: Enhance support for images, videos, and other media types
diff --git a/app/src/main/java/com/greybox/projectmesh/testing/README.md b/app/src/main/java/com/greybox/projectmesh/testing/README.md
index d6a22a482..7b4f428cb 100644
--- a/app/src/main/java/com/greybox/projectmesh/testing/README.md
+++ b/app/src/main/java/com/greybox/projectmesh/testing/README.md
@@ -9,17 +9,17 @@ Project Mesh includes built-in test users to help with development and testing.
The application includes two test users:
1. **Online Test Device**
- - Name: "Test Echo Device (Online)"
- - IP Address: 192.168.0.99
- - Status: Always appears as online
- - Behavior: Automatically responds to messages with an echo reply
+ - Name: "Test Echo Device (Online)"
+ - IP Address: 192.168.0.99
+ - Status: Always appears as online
+ - Behavior: Automatically responds to messages with an echo reply
2. **Offline Test Device**
- - Name: "Test Echo Device (Offline)"
- - IP Address: 192.168.0.98
- - Status: Always appears as offline
- - Status: Always appears as offline
- - Behavior: Messages can be sent but will remain stored locally
+ - Name: "Test Echo Device (Offline)"
+ - IP Address: 192.168.0.98
+ - Status: Always appears as offline
+ - Status: Always appears as offline
+ - Behavior: Messages can be sent but will remain stored locally
**Only Online User Shows Up as Online**:
@@ -35,6 +35,7 @@ The application includes two test users:
## Usage Examples
### Testing Message Delivery
+
1. Navigate to the Chat screen
2. Select "Test Echo Device (Online)" from the conversation list
3. Send a message
@@ -43,6 +44,7 @@ The application includes two test users:
### Testing Offline Message Behavior
+
1. Navigate to the Chat screen
2. Select "Test Echo Device (Offline)" from the conversation list
3. Send a message
@@ -74,9 +76,12 @@ const val TEST_DEVICE_NAME_OFFLINE = "Test Echo Device (Offline)"
## Test User Integration
### How Test Users Connect with the Project Mesh Architecture
+
Test users are integrated into several key components of the Project Mesh architecture to simulate real devices without requiring actual physical connections. Here's how they interface with the core systems:
+
1. TestDeviceService Integration
-```kotlin
+
+```kotlin
// In TestDeviceService.kt
companion object {
const val TEST_DEVICE_IP = "192.168.0.99"
@@ -119,22 +124,24 @@ companion object {
Log.e("TestDeviceService", "Failed to initialize test device", e)
}
}
-
+
// Additional methods for test device functionality...
}
```
+
2. Global App Integration
-```kotlin
+
+```kotlin
// In GlobalApp.kt
override fun onCreate() {
super.onCreate()
-
+
// Other initialization code...
//Initialize test device:
TestDeviceService.initialize()
Log.d("MainActivity", "Test device initialized")
-
+
// Test conversation setup
insertTestConversations()
}
@@ -197,8 +204,10 @@ fun insertTestConversations() {
}
}
```
-3. AppServer Integration
-```kotlin
+
+3. AppServer Integration
+
+```kotlin
// In AppServer.kt
fun sendChatMessageWithStatus(address: InetAddress, time: Long, message: String, f: URI?): Boolean {
try {
@@ -218,7 +227,7 @@ fun sendChatMessageWithStatus(address: InetAddress, time: Long, message: String,
Log.d("AppServer", "Test device echoed message: $message")
return true
}
-
+
// Normal chat message handling for real devices...
}
catch (e: Exception) {
@@ -241,22 +250,24 @@ fun requestRemoteUserInfo(remoteAddr: InetAddress, port: Int = DEFAULT_PORT) {
DeviceStatusManager.updateDeviceStatus(ipAddress, false)
return
}
-
+
// Normal remote user info handling for real devices...
}
```
-4. DeviceStatusManager Integration
-```kotlin
+
+4. DeviceStatusManager Integration
+
+```kotlin
// In DeviceStatusManager.kt
object DeviceStatusManager {
// Other properties and methods...
-
+
//special test device addresses that should be handled differently
private val specialDevices = setOf(
"192.168.0.99", // Online test device
"192.168.0.98" // Offline test device
)
-
+
fun updateDeviceStatus(ipAddress: String, isOnline: Boolean, verified: Boolean = false) {
//if this is a special device, handle according to its predefined status
if (ipAddress == "192.168.0.99") { // Online test device
@@ -276,21 +287,23 @@ object DeviceStatusManager {
Log.d("DeviceStatusManager", "Updated test device status for $ipAddress: offline")
return
}
-
+
// Normal device status handling for real devices...
}
-
+
fun verifyDeviceStatus(ipAddress: String) {
// Skip verification for special test devices
if (ipAddress in specialDevices) {
return
}
-
+
// Normal device verification for real devices...
}
}
```
+
5. NetworkServiceViewModel Integration
+
```kotlin
// In NetworkScreenViewModel.kt
init {
@@ -313,21 +326,23 @@ init {
}
}
```
+
6. ConversationsHomeScreen Integration
Test devices appear in the conversations list as either online or offline contacts, with special handling to ensure they have the correct status regardless of actual network conditions.
7. ChatScreen Integration
-```kotlin
+
+```kotlin
// In ChatScreenViewModel.kt
fun sendChatMessage(virtualAddress: InetAddress, message: String, file: URI?) {
// Other processing...
-
+
viewModelScope.launch {
//save to local database
db.messageDao().addMessage(messageEntity)
//update convo with the new message
// ...
-
+
if (isOnline) {
try {
// Send message to real device
@@ -340,4 +355,4 @@ fun sendChatMessage(virtualAddress: InetAddress, message: String, file: URI?) {
}
```
-The test user system integrates smoothly with the existing architecture by implementing specialized handling at key decision points throughout the codebase. This allows the test devices to behave consistently and predictably while reusing much of the same code path as real devices.
\ No newline at end of file
+The test user system integrates smoothly with the existing architecture by implementing specialized handling at key decision points throughout the codebase. This allows the test devices to behave consistently and predictably while reusing much of the same code path as real devices.
diff --git a/app/src/main/java/com/greybox/projectmesh/user/README.md b/app/src/main/java/com/greybox/projectmesh/user/README.md
index 4b7a58b6d..b9ac34ebe 100644
--- a/app/src/main/java/com/greybox/projectmesh/user/README.md
+++ b/app/src/main/java/com/greybox/projectmesh/user/README.md
@@ -1,12 +1,16 @@
# User Profiles in Project Mesh
## Overview
+
Project Mesh implements a user profile system that allows devices to identify themselves on the mesh network. User profiles consist of a unique identifier (UUID), a display name, and network address information. This system enables personalized messaging and device identification across the mesh network.
+
## Key Components
+
### User Entity
+
The core of the user profile system is the UserEntity class, which stores all user data:
-```kotlin
+```kotlin
// In UserEntity.kt
@Serializable
@Entity(tableName = "users")
@@ -18,9 +22,11 @@ data class UserEntity(
)
```
-### User Repository
+### User Repository
+
The UserRepository manages all database operations related to user profiles:
-```kotlin
+
+```kotlin
// In UserRepository.kt
class UserRepository(private val userDao: UserDao) {
@@ -49,8 +55,11 @@ class UserRepository(private val userDao: UserDao) {
// Other repository methods...
}
```
+
### UserData Access Object (DAO)
+
The UserDao interface defines database operations:
+
```kotlin
// In UserDao.kt
@Dao
@@ -79,12 +88,14 @@ interface UserDao {
```
## User Profile Lifecycle
+
### First-time Setup
When a user first launches the app, they go through an onboarding process to set up their profile:
-```kotlin
+
+```kotlin
// In OnboardingViewModel.kt
fun handleFirstTimeSetup(onComplete: () -> Unit) {
viewModelScope.launch {
@@ -108,6 +119,7 @@ fun handleFirstTimeSetup(onComplete: () -> Unit) {
```
### User Information Exchange
+
When devices connect, they exchange user information:
**Before Name Exchange**:
@@ -117,11 +129,11 @@ When devices connect, they exchange user information:
-```kotlin
+```kotlin
// In AppServer.kt - requesting user info
fun requestRemoteUserInfo(remoteAddr: InetAddress, port: Int = DEFAULT_PORT) {
// Special handling for test devices...
-
+
scope.launch {
try {
val url = "http://${remoteAddr.hostAddress}:$port/myinfo"
@@ -130,7 +142,7 @@ fun requestRemoteUserInfo(remoteAddr: InetAddress, port: Int = DEFAULT_PORT) {
val response = httpClient.newCall(request).execute()
val userJson = response.body?.string()
-
+
if (!userJson.isNullOrEmpty()) {
// Decode JSON
val remoteUser = json.decodeFromString(UserEntity.serializer(), userJson)
@@ -141,7 +153,7 @@ fun requestRemoteUserInfo(remoteAddr: InetAddress, port: Int = DEFAULT_PORT) {
remoteUserWithIp.name,
remoteUserWithIp.address
)
-
+
// Update user status...
}
} catch (e: Exception) {
@@ -172,16 +184,17 @@ private fun handleMyInfoRequest(): Response {
```
### Profile Updates
+
Users can update their profile information in the Settings screen:
-*Found in Settings Under Network > Device Name*:
+_Found in Settings Under Network > Device Name_:
-*User name can be Updated* :
+_User name can be Updated_ :
-```kotlin
+```kotlin
// In SettingsScreen.kt
onDeviceNameChange = { newDeviceName ->
Log.d("BottomNavApp", "Device name changed to: $newDeviceName")
@@ -197,7 +210,7 @@ onDeviceNameChange = { newDeviceName ->
name = newDeviceName,
address = appServer.localVirtualAddr.hostAddress
)
-
+
// 2. Broadcast updated name to connected users
val connectedUsers = userRepository.getAllConnectedUsers()
connectedUsers.forEach { user ->
@@ -216,17 +229,19 @@ onDeviceNameChange = { newDeviceName ->
```
### Online Status Tracking
+
The application tracks which users are online using the DeviceStatusManager:
-```kotlin
+
+```kotlin
// In DeviceStatusManager.kt
object DeviceStatusManager {
private val _deviceStatusMap = MutableStateFlow