Compare commits

..

7 Commits

Author SHA1 Message Date
metacryst
142d4a3fc3 Allow fetching from multiple sources 2026-04-16 18:27:24 -05:00
metacryst
0bb544e96c update version, incorporate error screen 2026-04-10 03:19:22 -05:00
metacryst
a104b43b24 error handling for no internet 2026-04-09 07:42:56 -05:00
metacryst
8d5a63b262 fetch everything remotely 2026-04-09 06:22:32 -05:00
14c885a60f Animation conflict fix 2026-04-06 16:47:07 -04:00
422e89caee Fixed serverFunctions naming issue 2026-04-06 12:25:47 -04:00
d0df371a3c Sidebar controls for calendar
- Added toggle for switching between day/week/month (calendar) in the sidebar
- Added a "lightdivider" shared.css var
2026-04-04 20:32:40 -04:00
79 changed files with 214 additions and 4632 deletions

View File

@@ -11,7 +11,7 @@
},
"plugins": {
"SplashScreen": {
"launchAutoHide": true
"launchAutoHide": false
}
}
}

View File

@@ -370,7 +370,7 @@
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.0.5;
MARKETING_VERSION = 1.0.6;
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = russell.sam.forum;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -392,7 +392,7 @@
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.0.5;
MARKETING_VERSION = 1.0.6;
PRODUCT_BUNDLE_IDENTIFIER = russell.sam.forum;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";

View File

@@ -29,6 +29,12 @@
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Used to find keep local information relevant.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Used to find forums and communities near you</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Access your photos to set a profile picture and share with others</string>
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
@@ -41,6 +47,8 @@
<array>
<string>armv7</string>
</array>
<key>UIRequiresFullScreen</key>
<true/>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
@@ -49,15 +57,7 @@
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
<key>UIRequiresFullScreen</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
<key>NSPhotoLibraryUsageDescription</key>
<string>Access your photos to set a profile picture and share with others</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Used to find keep local information relevant.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Used to find forums and communities near you</string>
</dict>
</plist>

View File

@@ -12,6 +12,7 @@ def capacitor_pods
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
pod 'CapacitorCamera', :path => '../../node_modules/@capacitor/camera'
pod 'CapacitorFilesystem', :path => '../../node_modules/@capacitor/filesystem'
pod 'CapacitorGeolocation', :path => '../../node_modules/@capacitor/geolocation'
pod 'CapacitorGoogleMaps', :path => '../../node_modules/@capacitor/google-maps'
pod 'CapacitorHaptics', :path => '../../node_modules/@capacitor/haptics'

View File

@@ -4,6 +4,9 @@ PODS:
- CapacitorCamera (7.0.2):
- Capacitor
- CapacitorCordova (7.4.4)
- CapacitorFilesystem (7.1.8):
- Capacitor
- IONFilesystemLib (~> 1.1.1)
- CapacitorGeolocation (7.1.5):
- Capacitor
- IONGeolocationLib (= 1.0.1)
@@ -26,12 +29,14 @@ PODS:
- GoogleMaps/Base (8.4.0)
- GoogleMaps/Maps (8.4.0):
- GoogleMaps/Base
- IONFilesystemLib (1.1.2)
- IONGeolocationLib (1.0.1)
DEPENDENCIES:
- "Capacitor (from `../../node_modules/@capacitor/ios`)"
- "CapacitorCamera (from `../../node_modules/@capacitor/camera`)"
- "CapacitorCordova (from `../../node_modules/@capacitor/ios`)"
- "CapacitorFilesystem (from `../../node_modules/@capacitor/filesystem`)"
- "CapacitorGeolocation (from `../../node_modules/@capacitor/geolocation`)"
- "CapacitorGoogleMaps (from `../../node_modules/@capacitor/google-maps`)"
- "CapacitorHaptics (from `../../node_modules/@capacitor/haptics`)"
@@ -43,6 +48,7 @@ SPEC REPOS:
trunk:
- Google-Maps-iOS-Utils
- GoogleMaps
- IONFilesystemLib
- IONGeolocationLib
EXTERNAL SOURCES:
@@ -52,6 +58,8 @@ EXTERNAL SOURCES:
:path: "../../node_modules/@capacitor/camera"
CapacitorCordova:
:path: "../../node_modules/@capacitor/ios"
CapacitorFilesystem:
:path: "../../node_modules/@capacitor/filesystem"
CapacitorGeolocation:
:path: "../../node_modules/@capacitor/geolocation"
CapacitorGoogleMaps:
@@ -69,6 +77,7 @@ SPEC CHECKSUMS:
Capacitor: 09d9ff8e9618e8c4b3cab2bbee34a17215dd2fef
CapacitorCamera: 6e18d54c8ab30d7dc7b8cd93d96f9b4f57e9202a
CapacitorCordova: bf648a636f3c153f652d312ae145fb508b6ffced
CapacitorFilesystem: f54cd6b76be06fa7ceb219cf313d32e0d626ea87
CapacitorGeolocation: b96474c3259dd4a294227ea8ec19140b1837cceb
CapacitorGoogleMaps: 20b5445a532f80dbb120fa99941fd094bcc88af6
CapacitorHaptics: d17da7dd984cae34111b3f097ccd3e21f9feec62
@@ -77,8 +86,9 @@ SPEC CHECKSUMS:
CapacitorSplashScreen: d06ae8804808e9f649a08e7bb7f283c77b688084
Google-Maps-iOS-Utils: 66d6de12be1ce6d3742a54661e7a79cb317a9321
GoogleMaps: 8939898920281c649150e0af74aa291c60f2e77d
IONFilesystemLib: 21a63377696b2d8fab5632ecfb7d2ac67bddb68a
IONGeolocationLib: 20f9d0248a0b5264511fb57a37e25dd2badf797a
PODFILE CHECKSUM: 7fad0e16088b635c7bc1980fea245d4a60cc4bbe
PODFILE CHECKSUM: 32ad5bbf56056f7ee8d159f9eae42fe03e911a61
COCOAPODS: 1.15.2

View File

@@ -1,6 +1,6 @@
{
"name": "capacitor-app",
"version": "1.0.0",
"name": "Forum",
"version": "1.0.1",
"description": "An Amazing Capacitor App",
"type": "module",
"keywords": [
@@ -15,6 +15,7 @@
"dependencies": {
"@capacitor/camera": "^7.0.2",
"@capacitor/core": "^7.4.4",
"@capacitor/filesystem": "^7.1.8",
"@capacitor/geolocation": "^7.1.5",
"@capacitor/google-maps": "^7.2.0",
"@capacitor/haptics": "^7.0.3",

View File

@@ -2,28 +2,15 @@
```npm run start```
### Browser: Dev Frontend and Dev Backend (localhost)
This option should be at the top level of capacitor.config.json
"server": {
"url": "http://sam.local:5173",
"cleartext": true
},
## Install Native Tools
### Browser: Prod Frontend and Prod Backend
Run:
vite build
npx serve dist
If you need to login again:
run localStorage.clear() in the browser dev tools console and then refresh the page.
## Run On Device
https://capacitorjs.com/docs/ios#adding-the-ios-platform
One-Time Install:
npm install @capacitor/ios
npx cap add ios
## Run On Device
To Open XCode:
npx cap open ios
@@ -33,18 +20,41 @@ npm run build && npx cap copy ios
If getting black screen:
npx cap sync iOS
### iOS: Dev Frontend and Dev Backend (localhost)
## iOS:
### Browser: Dev Front and Dev Back (localhost)
This option should be at the top level of capacitor.config.json
"server": {
"url": "http://sam.local:5173",
"cleartext": true
},
### iOS: Dev Frontend with Prod Backend (frm.so)
### Browser: Prod Front and Prod Back
Run:
vite build
npx serve dist
If you need to login again:
run localStorage.clear() in the browser dev tools console and then refresh the page.
## iOS:
### Dev Front, Dev Back (localhost)
This option should be at the top level of capacitor.config.json
"server": {
"url": "http://sam.local:5173",
"cleartext": true
},
### Dev Front, Prod Back (frm.so)
Add "https://frm.so" to VITE_API_URL in .env.development
### iOS: Prod Frontend and Prod Backend (frm.so)
Remove the "server" object from capacitor.config
### Prod Front, Prod Back (frm.so)
Remove the "server" object from capacitor.config.
### Various Commands
npx cap config - this will list the full configuration currently being used

View File

@@ -1 +0,0 @@
VITE_API_URL=https://frm.so

View File

@@ -1 +0,0 @@
VITE_API_URL=https://frm.so

View File

@@ -1,106 +0,0 @@
import { Preferences } from '@capacitor/preferences';
import "./Login.js";
import "./Signup.js"
import "./EnterCode.js"
class AuthPage extends Shadow {
inputStyles(el) {
return el
.background("var(--main)")
.color("var(--text)")
.border("1px solid var(--accent)")
.fontSize(0.9, rem)
.backgroundColor("var(--searchbackground)")
.borderRadius(12, px)
.outline("none")
.onTouch((start) => {
if(start) {
this.style.backgroundColor = "var(--accent)"
} else {
this.style.backgroundColor = "var(--searchbackground)"
}
})
}
render() {
VStack(() => {
img(window.matchMedia('(prefers-color-scheme: dark)').matches ? "/_/icons/columnwhite.svg" : "/_/icons/logo.svg", window.isMobile() ? "5vmax" : "3vmax")
.marginTop(5, em)
.marginLeft(2, em)
.onClick((done) => {
window.navigateTo("/")
})
HStack(() => {
p("Login")
.state(this, "selected", function (selected) {
if(selected === "1") {
this.fontWeight("bold")
this.background("var(--loginButton)")
} else {
this.fontWeight("normal")
this.background("transparent")
}
})
.padding(0.75, em)
.borderRadius(12, px)
.onTap(() => {
this.attr("selected", "1")
})
p("Enter Code")
.state(this, "selected", function (selected) {
if(selected === "2") {
this.fontWeight("bold")
this.background("var(--loginButton)")
} else {
this.fontWeight("normal")
this.background("transparent")
}
})
.padding(0.75, em)
.borderRadius(12, px)
.onTap(() => {
this.attr("selected", "2")
})
})
.fontFamily("Arial")
.padding(0.25, em)
.borderRadius(12, px)
.background("var(--loginBackground)")
.color("var(--text)")
.horizontalAlign("center")
.margin("auto")
.marginTop(7.5, em)
.marginBottom(2, em)
.gap(0.5, em)
ZStack(() => {
Login()
.state(this, "selected", function (selected) {
if(selected === "1") {
this.display("")
} else {
this.display("none")
}
})
EnterCode()
.state(this, "selected", function (selected) {
if(selected === "2") {
this.display("flex")
} else {
this.display("none")
}
})
})
})
.attr("selected", "1")
.width(100, vw)
.height(100, vh)
.margin(0)
}
}
register(AuthPage)

View File

@@ -1,101 +0,0 @@
import util from "../../util.js"
import "./Signup.js"
class EnterCode extends Shadow {
inputStyles(el) {
return el
.background("var(--main)")
.color("var(--text)")
.border("1px solid var(--accent)")
.fontSize(0.9, rem)
.backgroundColor("var(--searchbackground)")
.borderRadius(12, px)
.outline("none")
.onTouch((start) => {
if (start) {
this.style.backgroundColor = "var(--accent)"
} else {
this.style.backgroundColor = "var(--searchbackground)"
}
})
}
render() {
VStack(() => {
VStack(() => {
p("Enter the code given to you by your organization.")
.color("#614945")
.maxWidth(70, vw)
.marginTop(3, em)
input("Code", "70vw")
.attr({ name: "firstName", type: "text" })
.margin("auto")
.marginVertical(1, em)
.padding(1, em)
.styles(this.inputStyles)
button("==>")
.padding(1, em)
.fontSize(0.9, rem)
.borderRadius(12, px)
.background("var(--searchbackground)")
.color("var(--text)")
.border("1px solid var(--accent)")
.boxSizing("border-box")
.onTouch(function (start) {
if (start) {
this.style.backgroundColor = "var(--accent)"
} else {
this.style.backgroundColor = "var(--searchbackground)"
}
})
.onClick((done) => {
if (done) this.submit()
})
})
.state(this, "codeaccepted", function (accepted) {
if(!accepted) {
this.display("flex")
} else {
this.display("none")
}
})
Signup()
.state(this, "codeaccepted", function (accepted) {
if(accepted) {
this.display("")
} else {
this.display("none")
}
})
})
.horizontalAlign("center")
.display("flex")
this.style.display = "flex"
}
async submit() {
console.log("submit")
const res = await fetch(`${util.HOST}/auth/joincode`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', "Accept": "application/json", "X-Client": "mobile" },
body: JSON.stringify({ code: this.$("input").value })
});
if (res.ok) {
console.log("got join code succ")
this.attr("codeaccepted", "true")
let { networkId } = await res.json()
$("signup-").attr("networkid", networkId)
} else {
const { error } = await res.json();
console.error(error)
}
}
}
register(EnterCode)

View File

@@ -1,147 +0,0 @@
import { Preferences } from '@capacitor/preferences';
import util from "../../util.js"
class Login extends Shadow {
inputStyles(el) {
return el
.background("var(--main)")
.color("var(--text)")
.border("1px solid var(--accent)")
.fontSize(0.9, rem)
.backgroundColor("var(--searchbackground)")
.borderRadius(12, px)
.outline("none")
.onTouch((start) => {
if (start) {
this.style.backgroundColor = "var(--accent)"
} else {
this.style.backgroundColor = "var(--searchbackground)"
}
})
}
render() {
form(() => {
VStack(() => {
input("Email", "70vw")
.attr({ name: "email", type: "email" })
.margin("auto")
.marginVertical(1, em)
.padding(1, em)
.styles(this.inputStyles)
input("Password", "70vw")
.attr({ name: "password", type: "password" })
.margin("auto")
.marginVertical(1, em)
.padding(1, em)
.styles(this.inputStyles)
HStack(() => {
button("==>")
.padding(1, em)
.fontSize(0.9, rem)
.borderRadius(12, px)
.background("var(--searchbackground)")
.color("var(--text)")
.border("1px solid var(--accent)")
.boxSizing("border-box")
.onTouch(function (start) {
if (start) {
this.style.backgroundColor = "var(--accent)"
} else {
this.style.backgroundColor = "var(--searchbackground)"
}
})
})
.width(70, vw)
.margin("auto")
.fontSize(0.9, rem)
.paddingLeft(0, em)
.paddingRight(2, em)
.marginVertical(1, em)
.border("1px solid transparent")
p("")
.state("errortype", function (type) {
const messages = {
email: "Please enter a valid email.",
password: "Please enter a valid password.",
emailwrong: "Could not find an account with this email.",
passwordwrong: "Incorrect password.",
};
if(messages[type]) {
this.display("")
this.innerText = messages[type]
} else {
this.display("none")
this.innerText = ""
}
})
.margin("auto")
.marginTop(1, em)
.color("var(--text)")
.fontFamily("Arial")
.opacity(.7)
.padding(0.5, em)
.backgroundColor("var(--darkred)")
.display("none")
})
})
.height(100, pct)
.onSubmit(async (e) => {
e.preventDefault();
const data = {
email: e.target.$('[name="email"]').value,
password: e.target.$('[name="password"]').value,
};
await this.requestLogin(data);
})
}
isValidEmail = (email) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
isValidPassword = (password) => password.length >= 7;
async requestLogin(data) {
const emailValid = this.isValidEmail(data.email.trim() || "");
const passValid = this.isValidPassword(data.password.trim() || "");
if (!emailValid || !passValid) {
console.log("invalid", emailValid)
const errorType = !emailValid ? 'email' : 'password';
this.$("p").attr({ errorType });
return;
} else {
this.$("p").attr({ errorType: "" });
}
const res = await fetch(`${util.HOST}/auth/login`, {
method: "POST",
headers: { "Content-Type": "application/json", "X-Client": "mobile" },
body: JSON.stringify({
email: data["email"],
password: data["password"]
})
});
if (res.ok) {
const { token } = await res.json();
await Preferences.set({ key: 'auth_token', value: token });
global.renderHome();
} else {
const { error } = await res.json();
this.errorMessage = error;
console.error(error)
if(error.includes("email")) {
this.$("p").attr({ errorType: "emailwrong" });
} else {
this.$("p").attr({ errorType: "passwordwrong" });
}
}
}
}
register(Login)

View File

@@ -1,214 +0,0 @@
import { Preferences } from '@capacitor/preferences';
import util from "../../util.js"
class Signup extends Shadow {
inputStyles(el) {
return el
.background("var(--main)")
.color("var(--text)")
.border("1px solid var(--accent)")
.fontSize(0.9, rem)
.backgroundColor("var(--searchbackground)")
.borderRadius(12, px)
.outline("none")
.onTouch((start) => {
if (start) {
this.style.backgroundColor = "var(--accent)"
} else {
this.style.backgroundColor = "var(--searchbackground)"
}
})
}
render() {
form(() => {
VStack(() => {
input("First Name", "70vw")
.attr({ name: "firstName", type: "text" })
.margin("auto")
.marginVertical(1, em)
.padding(1, em)
.styles(this.inputStyles)
input("Last Name", "70vw")
.attr({ name: "lastName", type: "text" })
.margin("auto")
.marginVertical(1, em)
.padding(1, em)
.styles(this.inputStyles)
input("Email", "70vw")
.attr({ name: "email", type: "email" })
.margin("auto")
.marginVertical(1, em)
.padding(1, em)
.styles(this.inputStyles)
input("Password", "70vw")
.attr({ name: "password", type: "password" })
.margin("auto")
.marginVertical(1, em)
.padding(1, em)
.styles(this.inputStyles)
input("Confirm Password", "70vw")
.attr({ name: "confirmPassword", type: "password" })
.margin("auto")
.marginVertical(1, em)
.padding(1, em)
.styles(this.inputStyles)
p("")
.state("errormessage", function (msg) {
if(msg) {
this.display("")
this.innerText = msg
} else {
this.display("none")
this.innerText = ""
}
})
.margin("auto")
.marginTop(1, em)
.color("var(--text)")
.fontFamily("Arial")
.opacity(.7)
.padding(0.5, em)
.backgroundColor("var(--darkred)")
.display("none")
HStack(() => {
button("==>")
.padding(1, em)
.fontSize(0.9, rem)
.borderRadius(12, px)
.background("var(--searchbackground)")
.color("var(--text)")
.border("1px solid var(--accent)")
.boxSizing("border-box")
.onTouch(function (start) {
if (start) {
this.style.backgroundColor = "var(--accent)"
} else {
this.style.backgroundColor = "var(--searchbackground)"
}
})
})
.width(70, vw)
.margin("auto")
.fontSize(0.9, rem)
.paddingLeft(0, em)
.paddingRight(2, em)
.marginVertical(1, em)
.marginBottom(10, em)
.border("1px solid transparent")
})
})
.height(100, pct)
.onSubmit(async (e) => {
e.preventDefault();
const data = new FormData(e.target);
if (this.verifyInput(data)) {
await this.requestSignup(data);
} else {
console.log(this.errorMessage)
}
})
}
/*
*******************************************************************************
NO LONGER WORKS - SEE AUTH ENDPOINT IN SERVER
*******************************************************************************
*/
async requestSignup(data) {
const networkId = this.attr("networkid");
const res = await fetch(`${util.HOST}/auth/signup`, {
method: "POST",
headers: { "Content-Type": "application/json", "X-Client": "mobile" },
body: JSON.stringify({
networkId: networkId,
firstName: data.get("firstName"),
lastName: data.get("lastName"),
email: data.get("email"),
password: data.get("password")
})
});
if (res.ok) {
const { token } = await res.json();
await Preferences.set({ key: 'auth_token', value: token });
global.renderHome();
} else {
const { error } = await res.json();
console.error(error)
this.$("p").attr("errormessage", error)
}
}
verifyInput(data) {
const firstName = data.get("firstName");
const lastName = data.get("lastName");
const email = data.get("email");
const password = data.get("password");
const confirmPassword = data.get("confirmPassword");
if (!firstName || firstName.trim() === "") {
this.$("p").attr("errormessage", "First name is required.")
return false
} else if (firstName.trim().length < 2) {
this.$("p").attr("errormessage", "First name must be at least 2 characters.")
return false
} else if (!/^[a-zA-Z\s'-]+$/.test(firstName.trim())) {
this.$("p").attr("errormessage", "First name contains invalid characters.")
return false
}
if (!lastName || lastName.trim() === "") {
this.$("p").attr("errormessage", "Last name is required.")
return false
} else if (lastName.trim().length < 2) {
this.$("p").attr("errormessage", "Last name must be at least 2 characters.")
return false
} else if (!/^[a-zA-Z\s'-]+$/.test(lastName.trim())) {
this.$("p").attr("errormessage", "Last name contains invalid characters.")
return false
}
if (!email || email.trim() === "") {
this.$("p").attr("errormessage", "Email is required.")
return false
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.trim())) {
this.$("p").attr("errormessage", "Please enter a valid email address.")
return false
}
let passwordError = `Password must be at least 7 characters and include an uppercase letter, a lowercase letter, a number, and a special character (!@#$%^&*(),.?":{}|<>)`
if (!password) {
this.$("p").attr("errormessage", "Password is required.")
return false
} else if (password.length < 7) {
this.$("p").attr("errormessage", passwordError)
return false
} else if (!/[A-Z]/.test(password)) {
this.$("p").attr("errormessage", passwordError)
return false
} else if (!/[a-z]/.test(password)) {
this.$("p").attr("errormessage", passwordError)
return false
} else if (!/[0-9]/.test(password)) {
this.$("p").attr("errormessage", passwordError)
return false
} else if (!/[!@#$%^&*(),.?":{}|<>]/.test(password)) {
this.$("p").attr("errormessage", passwordError)
return false
}
if (!confirmPassword) {
this.$("p").attr("errormessage", "Please confirm your password.")
return false
} else if (confirmPassword !== password) {
this.$("p").attr("errormessage", "Passwords do not match.")
return false
}
return true;
}
}
register(Signup)

View File

@@ -1,23 +0,0 @@
class ConnectionError extends Shadow {
render() {
VStack(() => {
img("/_/icons/column.svg", window.isMobile() ? "5vmax" : "3vmax")
.position("absolute")
.top(2, em)
.left(2, em)
.onClick((done) => {
window.navigateTo("/")
})
p("Error connecting to server. Please try again later!")
})
.verticalAlign("center")
.paddingHorizontal(20, vw)
.backgroundColor("var(--main)")
.overflowX("hidden")
.height(100, vh)
}
}
register(ConnectionError)

View File

@@ -1,153 +0,0 @@
import "../components/Sidebar.js"
import "../components/AppMenu.js"
import "../components/AppWindowContainer.js"
css(`
#homeContainer {
-webkit-user-select: none;
}
`)
/*
Sidebar Functionality Checklist:
- Open on Top left network logo touch (WITH transition)
- Follow finger on swipe from left side of the screen
- Open if finger swipw travels far enough to the right (WITH velocity-based transition)
- Re-close if not opened enough of the way (WITH transition)
- Close on touch of home contents (WITH transition)
- Follow finger on swipe beginning near or anywhere on right of divider between sidebar and home contents
- Close if finger swipe travels far enough to the left (WITH velocity-based transition)
- Re-open if not closed enough of the way (WITH transition)
*/
class Home extends Shadow {
dragStartX = null
sidebarOpen = false
SIDEBAR_FULL_OPEN = (window.outerWidth * 5) / 6
SIDEBAR_START_THRESHOLD = window.outerWidth / 10
SIDEBAR_CLOSE_DECISION = (window.outerWidth * 2) / 3
SIDEBAR_OPEN_DECISION = (window.outerWidth / 3)
constructor() {
super()
}
render() {
ZStack(() => {
Sidebar(this.SIDEBAR_FULL_OPEN)
ZStack(() => {
VStack(() => {
AppWindowContainer()
AppMenu()
})
.height(100, pct)
.minHeight(0)
})
.left(0, px)
.backgroundColor("var(--main)")
.overflowX("hidden")
.height(window.visualViewport.height, px)
.position("fixed")
.borderLeft("1px solid var(--accent)")
.onTouch((start, e) => {
if(this.sidebarOpen) {
this.sidebarOpenTouch(start, e)
} else {
this.sidebarClosedTouch(start, e)
}
})
.attr({ id: "homeContainer" })
})
.userSelect("none")
}
openSidebar(duration = 200) {
const home = this.$("#homeContainer");
home.style.transition = `left ${duration}ms`;
home.style.left = `${this.SIDEBAR_FULL_OPEN}px`;
this.sidebarOpen = true;
this.dragStartX = null
setTimeout(() => home.style.transition = "", duration);
}
closeSidebar(duration = 200) {
const home = this.$("#homeContainer");
home.style.transition = `left ${duration}ms`;
home.style.left = "0px";
this.sidebarOpen = false;
this.dragStartX = null
setTimeout(() => home.style.transition = "", duration);
}
sidebarOpenTouch(start, e) {
if(start) {
let amount = e.targetTouches[0].clientX
if(amount > (this.SIDEBAR_FULL_OPEN - this.SIDEBAR_START_THRESHOLD)) {
this.dragStartX = e.touches[0].clientX
this.dragStartTime = Date.now(); // ⬅ track start time
document.addEventListener("touchmove", this.moveSidebar)
}
} else {
if(!this.dragStartX) return;
let endX = e.changedTouches[0].clientX
let duration = this.getDuration(this.dragStartX, endX);
if(Math.abs(this.dragStartX - endX) < 5) { // 2 conditions are separated so this one doesn't close instantly
this.closeSidebar()
} else if(endX < this.SIDEBAR_CLOSE_DECISION) {
this.closeSidebar(duration)
} else {
this.openSidebar(duration)
}
document.removeEventListener("touchmove", this.moveSidebar)
}
}
sidebarClosedTouch(start, e) {
if(start) {
let amount = e.targetTouches[0].clientX
if(amount < this.SIDEBAR_START_THRESHOLD) {
this.dragStartX = e.touches[0].clientX
this.dragStartTime = Date.now();
document.addEventListener("touchmove", this.moveSidebar)
}
} else {
if(!this.dragStartX) return;
let endX = e.changedTouches[0].clientX
let duration = this.getDuration(this.dragStartX, endX);
if(endX > this.SIDEBAR_OPEN_DECISION) {
this.openSidebar(duration)
} else {
this.closeSidebar(duration)
}
document.removeEventListener("touchmove", this.moveSidebar)
}
}
moveSidebar = (e) => {
let amount = e.targetTouches[0].clientX
if(e.targetTouches[0] && amount < this.SIDEBAR_FULL_OPEN) {
this.$("#homeContainer").style.left = `${amount}px`
}
}
getDuration(startX, endX) {
const distance = Math.abs(endX - startX);
const elapsed = Date.now() - this.dragStartTime;
const velocity = distance / elapsed; // px per ms
const duration = Math.round(distance / velocity); // time to cover remaining distance
return Math.min(Math.max(duration, 50), 200); // clamp between 50ms and 200ms
}
}
register(Home)

View File

@@ -1,61 +0,0 @@
class Login extends Shadow {
inputStyles(el) {
return el
.background("var(--main)")
.color("var(--text)")
.border("1px solid var(--accent)")
.fontSize(0.9, rem)
.backgroundColor("var(--accentdark)")
.borderRadius(12, px)
.outline("none")
.onTouch((start) => {
if(start) {
this.style.backgroundColor = "var(--accent)"
} else {
this.style.backgroundColor = "var(--accentdark)"
}
})
}
render() {
ZStack(() => {
img(window.matchMedia('(prefers-color-scheme: dark)') ? "/_/icons/columnwhite.svg" : "/_/icons/logo.svg", window.isMobile() ? "5vmax" : "3vmax")
.position("absolute")
.top(5, em)
.left(2, em)
.onClick((done) => {
window.navigateTo("/")
})
form(() => {
input("Email", "70vw")
.attr({name: "email", type: "email"})
.margin(1, em)
.padding(1, em)
.styles(this.inputStyles)
input("Password", "70vw")
.attr({name: "password", type: "password"})
.margin(1, em)
.padding(1, em)
.styles(this.inputStyles)
button("==>")
.margin(1, em)
.padding(1, em)
.fontSize(0.9, rem)
.borderRadius(12, px)
.background("var(--accent)")
.color("var(--text)")
.border("1px solid var(--accent)")
})
.attr({action: "/login", method: "POST"})
.x(50, vw).y(50, vh)
.center()
})
.background("var(--main)")
.width(100, vw)
.height(100, pct)
.margin(0)
}
}
register(Login)

View File

@@ -1,222 +0,0 @@
import util from "../util";
css(`
profile- textarea::-webkit-scrollbar {
display: none;
width: 0px;
height: 0px;
}
profile- textarea::-webkit-scrollbar-thumb {
background: transparent;
}
profile- textarea::-webkit-scrollbar-track {
background: transparent;
}
`)
class Profile extends Shadow {
constructor() {
super()
this.profile = global.profile
this.bioText = global.profile.bio ?? ""
}
render() {
ZStack(() => {
div("➩")
.width(3, rem)
.height(3, rem)
.borderRadius(50, pct)
.border("1.5px solid var(--divider)")
.position("absolute")
.fontSize(2, em)
.transform("rotate(180deg)")
.top(3, rem)
.left(2, rem)
.zIndex(1001)
.display("flex")
.alignItems("center")
.justifyContent("center")
.transition("scale .2s")
.state("touched", function (touched) {
if(touched) {
this.scale("1.5")
this.color("var(--darkaccent)")
this.backgroundColor("var(--divider)")
} else {
this.scale("")
this.color("var(--divider)")
this.backgroundColor("var(--darkaccent)")
}
})
.onTouch(function (start) {
if(start) {
this.attr({touched: "true"})
} else {
this.attr({touched: ""})
}
})
.onClick((done) => {
if(done)
$("appwindowcontainer-").closeProfile()
})
form(() => {
input("Image Upload", "0px", "0px")
.attr({ name: "image-upload", type: "file" })
.display("none")
.visibility("hidden")
.onChange((e) => {
this.handleUpload(e.target.files[0]);
})
VStack(() => {
HStack(() => {
if (global.profile.image_path) {
img(`${util.HOST}${global.profile.image_path}`, "10em", "10em")
.borderRadius(100, pct)
}
})
.boxSizing("border-box")
.height(10, em)
.width(10, em)
.border("1px solid var(--accent)")
.borderRadius(100, pct)
.background("var(--darkaccent)")
.onTap(() => {
const inputSelector = this.$('[name="image-upload"]');
inputSelector.click()
})
p("Tap to edit")
.color("var(--headertext)")
.opacity(0.5)
.marginTop(0.5, em)
h1(this.profile.first_name + " " + this.profile.last_name)
.color("var(--headertext")
.width(70, pct)
.marginVertical(0.25, em)
.textAlign("center")
p("Joined " + this.convertDate(this.profile.created))
.color("var(--headertext)")
.marginBottom(0.5, em)
h2("Bio")
.color("var(--headertext")
.margin(0)
.paddingVertical(0.9, em)
.borderTop("2px solid var(--divider)")
.width(70, pct)
.textAlign("center")
textarea(this.bioText ? this.bioText : "Tap to start typing...")
.attr({ name: "bioinput" })
.padding(1, em)
.width(90, pct)
.height(15, em)
.boxSizing("border-box")
.background("var(--searchbackground)")
.color("var(--darktext)")
.border("1px solid color-mix(in srgb, var(--accent) 60%, transparent)")
.borderRadius(12, px)
.fontFamily("Arial")
.fontSize(1.1, em)
.outline("none")
.onAppear((e) => {
if (this.bioText) {
$("profile- textarea").innerText = this.bioText
}
})
.lineHeight(1.2, em)
button("Save Bio")
.padding(1, em)
.fontSize(1.1, em)
.borderRadius(12, px)
.background("var(--searchbackground)")
.color("var(--text)")
.border("1px solid var(--accent)")
.boxSizing("border-box")
.marginVertical(0.75, em)
})
.horizontalAlign("center")
.marginTop(5, em)
})
.onSubmit(async (e) => {
e.preventDefault();
const newBio = new FormData(e.target).get("bioinput");
console.log(this.profile)
if (newBio.trim() !== this.profile.bio?.trim()) {
const result = await server.editBio(newBio, this.profile.id)
const { bio, updated_at } = result.data
global.profile.bio = bio
global.profile.updated_at = updated_at
this.profile = global.profile
}
})
})
.backgroundColor("var(--main)")
.overflowX("hidden")
.height(window.visualViewport.height - 20, px)
.boxSizing("border-box")
.width(100, pct)
.position("fixed")
.top(100, vh)
.zIndex(5)
.transition("top .4s ")
.pointerEvents("none")
}
async handleUpload(file) {
try {
const body = new FormData();
body.append('image', file);
const res = await util.authFetch(`${util.HOST}/profile/upload-image`, {
method: "POST",
credentials: "include",
headers: {
"Accept": "application/json"
},
body: body
});
if(res.status === 401) {
return res.status
}
if (!res.ok) return res.status;
const data = await res.json()
global.profile = data.member
console.log(global.profile)
} catch (err) { // Network error / Error reaching server
console.error(err);
}
}
convertDate(rawDate) {
const parsed = new Date(rawDate);
if (isNaN(parsed.getTime())) return rawDate;
const month = parsed.toLocaleString("en-US", { month: "long", timeZone: "UTC" });
const day = parsed.getUTCDate();
const year = parsed.getUTCFullYear();
const ordinal = (n) => {
const mod100 = n % 100;
if (mod100 >= 11 && mod100 <= 13) return `${n}th`;
switch (n % 10) {
case 1: return `${n}st`;
case 2: return `${n}nd`;
case 3: return `${n}rd`;
default: return `${n}th`;
}
};
return `${month} ${ordinal(day)}, ${year}`;
}
}
register(Profile)

View File

@@ -1,112 +0,0 @@
:root {
--main: #FFE9C8;
--accent: #570b0b;
--darkaccent: #dfc9ac;
--text: #340000;
--yellow: #f1f3c3;
--bone: #fff2e7;
--gold: #FEBA7D;
--divider: #bb7c36;
--green: #0857265c;
--red: #ff0000;
--quillred: #DE3F3F;
--darkred: #6b2c1d;
--brown: #812A18;
--sidebar: #698b6f;
--divider: #523636;
--lightDivider: #52363681;
--darkbrown: #3f0808;
--darkgrey: #5c4646;
--headertext: #433c36e2;
--searchbackground: #ffeed8;
--loginButton: var(--main);
--loginBackground: #d96b6b;
--home-src: /_/icons/home.svg;
--home-selected-src: /_/icons/homelightselected.svg;
--people-src: /_/icons/people.svg;
--people-selected-src: /_/icons/peoplelightselected.svg;
--settings-src: /_/icons/settings.svg;
--settings-selected-src: /_/icons/settingslightselected.svg;
--events-src: /_/icons/events.svg;
--events-selected-src: /_/icons/eventslightselected.svg;
--jobs-src: /_/icons/jobs.svg;
--jobs-selected-src: /_/icons/jobslightselected.svg;
--column-src: /_/icons/column2.svg;
--nodes-src: /_/icons/nodes.svg;
--forum-src: /_/icons/forum.svg;
--trash-src: /_/icons/trash.svg;
--pin-src: /_/icons/pin.svg;
--time-src: /_/icons/time.svg;
--top-inset: env(safe-area-inset-top, 0px);
--bottom-inset: env(safe-area-inset-bottom, 0px);
}
@media (prefers-color-scheme: dark) {
:root {
--main: #2A150E;
--accent: #3D2622;
--darkaccent: #240609;
--text: #FADFB6;
--sidebar: #240609;
--divider: #523636;
--lightDivider: #52363680;
--darktext: #62473E;
--headertext: #ffd8bb;
--darkred: #6b2c1d;
--searchbackground: #260F0C;
--loginButton: var(--darkaccent);
--loginBackground: var(--accent);
--home-src: /_/icons/homelight.svg;
--home-selected-src: /_/icons/homelightselected.svg;
--people-src: /_/icons/peoplelight.svg;
--people-selected-src: /_/icons/peoplelightselected.svg;
--settings-src: /_/icons/settingslight.svg;
--settings-selected-src: /_/icons/settingslightselected.svg;
--events-src: /_/icons/eventslight.svg;
--events-selected-src: /_/icons/eventslightselected.svg;
--jobs-src: /_/icons/jobslight.svg;
--jobs-selected-src: /_/icons/jobslightselected.svg;
--column-src: /_/icons/column2.svg;
--nodes-src: /_/icons/nodes.svg;
--forum-src: /_/icons/forum.svg;
--trash-src: /_/icons/trash.svg;
--pin-src: /_/icons/pinlight.svg;
--time-src: /_/icons/timelight.svg;
}
}
input {
outline: none;
caret-color: var(--text); /* hide real caret */
}
input::placeholder {
font-family: Arial;
color: #5C504D;
}
html,
body {
padding: 0;
margin: 0;
font-family: Arial;
}
body {
background-color: var(--main);
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}

View File

@@ -1,68 +0,0 @@
import { Preferences } from '@capacitor/preferences';
import util from "../../../util.js"
class Connection {
connectionTries = 0;
ws;
receiveCB;
constructor(receiveCB) {
this.receiveCB = receiveCB;
}
init = async () => {
const { value: token } = await Preferences.get({ key: 'auth_token' });
return new Promise((resolve, reject) => {
let url = ""
if(util.HOST) {
url = "wss://" + util.HOST.replace(/^https?:\/\//, '') + "/ws" + `?token=${token}`;
} else {
url = "ws://" + window.location.host + "/ws"
}
this.ws = new WebSocket(url);
this.ws.addEventListener('open', () => {
this.connectionTries = 0;
console.log("WebSocket connection established.");
this.ws.addEventListener('message', this.receiveCB);
resolve(this.ws); // resolve when open
});
this.ws.addEventListener('close', () => {
console.log('WebSocket closed');
this.checkOpen(); // attempt reconnection
});
this.ws.addEventListener('error', (err) => {
console.error('WebSocket error', err);
reject(err); // reject if error occurs
});
});
}
checkOpen = async () => {
if (this.ws.readyState === WebSocket.OPEN) {
return true;
} else {
await this.sleep(this.connectionTries < 20 ? 5000 : 60000);
this.connectionTries++;
console.log('Reestablishing connection');
await this.init();
}
}
sleep = (time) => new Promise(resolve => setTimeout(resolve, time));
send = (msg) => {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(msg);
} else if (this.connectionTries === 0) {
setTimeout(() => this.send(msg), 100);
} else {
console.error('No WebSocket connection: Cannot send message');
}
}
}
export default Connection;

View File

@@ -1,49 +0,0 @@
import Connection from "./Connection.js";
export default class Socket {
connection;
disabled = true;
requestID = 1;
pending = new Map();
constructor() {
this.connection = new Connection(this.receive);
}
async init() {
await this.connection.init()
}
isOpen() {
if(this.connection.checkOpen()) {
return true;
} else {
return false;
}
}
send(msg) {
return new Promise(resolve => {
const id = (++this.requestID).toString();
this.pending.set(id, resolve);
this.connection.send(JSON.stringify({ id, ...msg }));
});
}
receive = (event) => {
const msg = JSON.parse(event.data);
if (msg.id && this.pending.has(msg.id)) {
this.pending.get(msg.id)(msg);
this.pending.delete(msg.id);
return;
} else {
this.onBroadcast(msg)
}
}
onBroadcast(msg) {
window.dispatchEvent(new CustomEvent(msg.event, {
detail: msg.msg
}));
}
}

View File

@@ -1 +0,0 @@
export default {}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,83 +0,0 @@
// import './ForumPanel.js'
// css(`
// forum- {
// font-family: 'Bona';
// }
// forum- input::placeholder {
// font-family: 'Bona Nova';
// font-size: 0.9em;
// color: var(--accent);
// }
// input::placeholder {
// font-family: Arial;
// }
// input[type="checkbox"] {
// appearance: none; /* remove default style */
// -webkit-appearance: none;
// width: 1em;
// height: 1em;
// border: 1px solid var(--accent);
// }
// input[type="checkbox"]:checked {
// background-color: var(--red);
// }
// `)
// class Forum extends Shadow {
// render() {
// ZStack(() => {
// VStack(() => {
// ForumPanel()
// input("Message", "70%")
// .paddingVertical(0.75, em)
// .boxSizing("border-box")
// .paddingHorizontal(2, em)
// .color("var(--accent)")
// .background("black")
// .marginBottom(1, em)
// .border("0.5px solid #6f5e4e")
// .borderRadius(100, px)
// .fontFamily("Arial")
// .fontSize(1, em)
// .onKeyDown(async function(e) {
// if (e.key === "Enter") {
// let msg = {
// forum: global.currentNetwork.abbreviation,
// text: this.value
// }
// await global.Socket.send({
// app: "FORUM",
// operation: "SEND",
// msg: msg
// })
// this.value = ""
// }
// })
// })
// .gap(0.5, em)
// .boxSizing("border-box")
// .width(100, pct)
// .height(100, pct)
// .horizontalAlign("center")
// .verticalAlign("end")
// .minHeight(0)
// })
// .backgroundColor("var(--main)")
// .boxSizing("border-box")
// .paddingVertical(1, em)
// .width(100, pct)
// .minHeight(0)
// .flex("1 1 auto")
// }
// }
// register(Forum)

View File

@@ -1,193 +0,0 @@
// import "../../components/LoadingCircle.js"
// css(`
// forumpanel- {
// scrollbar-width: none;
// -ms-overflow-style: none;
// }
// forumpanel-::-webkit-scrollbar {
// display: none;
// width: 0px;
// height: 0px;
// }
// forumpanel-::-webkit-scrollbar-thumb {
// background: transparent;
// }
// forumpanel-::-webkit-scrollbar-track {
// background: transparent;
// }
// `)
// class ForumPanel extends Shadow {
// messages = []
// isSending = false
// render() {
// VStack(() => {
// if(this.messages.length > 0) {
// let previousDate = null
// for(let i=0; i<this.messages.length; i++) {
// let message = this.messages[i]
// const isMe = message.authorId === global.profile.id
// const dateParts = this.parseDate(message.time);
// const { date, time } = dateParts;
// if (previousDate !== date) {
// previousDate = date;
// p(date)
// .textAlign("center")
// .opacity(0.6)
// .fontWeight("bold")
// .paddingTop(1, em)
// .paddingBottom(0.5, em)
// .color("var(--quillred)")
// .borderTop(`1px solid var(--${i == 0 ? "transparent" : "divider"})`)
// }
// VStack(() => {
// HStack(() => {
// h3(isMe ? "Me" : message.sentBy)
// .color(isMe ? "var(--quillred)" : "var(--brown")
// .margin(0)
// h3(`${date} ${time}`)
// .opacity(0.5)
// .color("var(--brown)")
// .margin(0)
// .marginLeft(0.5, em)
// .fontSize(1, em)
// if (message.edited) {
// p("(edited)")
// .color("var(--brown)")
// .letterSpacing(0.8, "px")
// .opacity(0.8)
// .fontWeight("bold")
// .paddingLeft(0.25, em)
// .fontSize(0.9, em)
// }
// })
// .verticalAlign("center")
// .marginBottom(0.1, em)
// p(message.text)
// .color("var(--accent)")
// .borderLeft("1.5px solid var(--divider)")
// .borderBottomLeftRadius("7.5px")
// .paddingLeft(0.5, em)
// .marginHorizontal(0.2, em)
// .paddingVertical(0.2, em)
// .boxSizing("border-box")
// })
// .marginBottom(0.05, em)
// .onClick(async (finished, e) => {
// if (finished) {
// console.log(message.id)
// let msg = {
// forum: global.currentNetwork.abbreviation,
// id: message.id,
// text: "EDITED TEXT TEST!"
// }
// await global.Socket.send({
// app: "FORUM",
// operation: "PUT",
// msg: msg
// })
// }
// })
// }
// } else {
// LoadingCircle()
// }
// })
// .gap(1, em)
// .fontSize(1.1, em)
// .boxSizing("border-box")
// .flex("1 1 auto")
// .minHeight(0)
// .overflowY("auto")
// .width(100, pct)
// .paddingBottom(2, em)
// .paddingHorizontal(4, pct)
// .backgroundColor("var(--main)")
// .onAppear(async () => {
// requestAnimationFrame(() => {
// this.scrollTo({ top: 0, behavior: "smooth" });
// });
// if (!this.isSending) {
// this.isSending = true
// let res = await global.Socket.send({
// app: "FORUM",
// operation: "GET",
// msg: {
// forum: global.currentNetwork.abbreviation,
// by: "network",
// authorId: -999 // default
// }
// })
// if(!res) console.error("failed to get messages")
// if(res.msg.length > 0 && this.messages.length === 0) {
// this.messages = res.msg.reverse()
// this.rerender()
// }
// this.isSending = false
// }
// })
// .onEvent("new-post", this.onNewPost)
// .onEvent("deleted-post", this.onDeletedPost)
// .onEvent("edited-post", this.onEditedPost)
// }
// onNewPost = (e) => {
// let newPost = e.detail
// if (this.messages && !this.messages.some(post => post.id === newPost.id)) {
// this.messages.unshift(newPost)
// this.rerender()
// }
// }
// onDeletedPost = (e) => {
// let deletedId = e.detail
// const i = this.messages.findIndex(post => post.id === deletedId)
// if (i !== -1) this.messages.splice(i, 1);
// this.rerender()
// }
// onEditedPost = (e) => {
// let editedPost = e.detail
// const i = this.messages.findIndex(post => post.id === editedPost.id)
// if (i !== -1) {
// this.messages.splice(i, 1)
// this.messages.unshift(editedPost)
// }
// this.rerender()
// }
// parseDate(str) {
// // Format: MM.DD.YYYY-HH:MM:SSxxxxxx(am|pm)
// const match = str.match(/^(\d{1,2})\.(\d{1,2})\.(\d{4})-(\d{1,2}):(\d{2}).*(am|pm)$/i);
// if (!match) return null;
// const [, mm, dd, yyyy, hh, min, ampm] = match;
// const date = `${mm}/${dd}/${yyyy}`;
// const time = `${hh}:${min}${ampm.toLowerCase()}`;
// return { date, time };
// }
// formatTime(str) {
// const match = str.match(/-(\d+:\d+):\d+.*(am|pm)/i);
// if (!match) return null;
// const [_, hourMin, ampm] = match;
// return hourMin + ampm.toLowerCase();
// }
// }
// register(ForumPanel)

View File

@@ -1,105 +0,0 @@
import "./MarketSidebar.js"
import "./MarketGrid.js"
css(`
market- {
font-family: 'Bona';
}
market- input::placeholder {
font-family: 'Bona Nova';
font-size: 0.9em;
color: var(--accent);
}
input[type="checkbox"] {
appearance: none; /* remove default style */
-webkit-appearance: none;
width: 1em;
height: 1em;
border: 1px solid var(--accent);
}
input[type="checkbox"]:checked {
background-color: var(--red);
}
`)
class Market extends Shadow {
listings = [
{
title: "Shield Lapel Pin",
stars: "5",
reviews: 1,
price: "$12",
company: "Hyperia",
type: "new",
image: "/db/images/1",
madeIn: "America"
}
]
render() {
ZStack(() => {
HStack(() => {
MarketSidebar()
MarketGrid(this.listings)
})
.width(100, "%")
.x(0).y(13, vh)
HStack(() => {
input("Search for products... (Coming Soon!)", "45vw")
.attr({
"type": "text",
"disabled": "true"
})
.fontSize(1.1, em)
.paddingLeft(1.3, em)
.background("transparent")
.border("0.5px solid var(--divider)")
.outline("none")
.color("var(--accent)")
.opacity(0.5)
.borderRadius(10, px)
.background("grey")
.cursor("not-allowed")
button("+ Add Item")
.width(7, em)
.marginLeft(1, em)
.borderRadius(10, px)
.background("transparent")
.border("0.5px solid var(--accent2)")
.color("var(--accent)")
.fontFamily("Bona Nova")
.onHover(function (hovering) {
if(hovering) {
this.style.background = "var(--green)"
} else {
this.style.background = "transparent"
}
})
.onClick((clicking) => {
console.log(this, "clicked")
})
})
.x(55, vw).y(4, vh)
.position("absolute")
.transform("translateX(-50%)")
})
.width(100, "%")
.height(100, "%")
}
connectedCallback() {
// Optional additional logic
}
}
register(Market)

View File

@@ -1,140 +0,0 @@
class MarketGrid extends Shadow {
listings;
constructor(listings) {
super()
this.listings = listings
}
boldUntilFirstSpace(text) {
if(!text) return
const index = text.indexOf(' ');
if (index === -1) {
// No spaces — bold the whole thing
return `<b>${text}</b>`;
}
return `<b>${text.slice(0, index)}</b>${text.slice(index)}`;
}
render() {
VStack(() => {
h3("Results")
.marginTop(0.1, em)
.marginBottom(1, em)
.marginLeft(0.4, em)
.color("var(--accent)")
.opacity(0.7)
if (this.listings.length > 0) {
ZStack(() => {
// BuyModal()
let params = new URLSearchParams(window.location.search);
const hyperiaMade = params.get("hyperia-made") === "true";
const americaMade = params.get("america-made") === "true";
const newItem = params.get("new") === "true";
const usedItem = params.get("used") === "true";
let filtered = this.listings;
if (hyperiaMade) {
filtered = filtered.filter(item => item.madeIn === "Hyperia");
}
if (americaMade) {
filtered = filtered.filter(item => item.madeIn === "America");
}
if (newItem) {
filtered = filtered.filter(item => item.type === "new");
}
if (usedItem) {
filtered = filtered.filter(item => item.type === "used");
}
for (let i = 0; i < filtered.length; i++) {
const rating = filtered[i].stars
const percent = (rating / 5)
VStack(() => {
img(filtered[i].image)
.marginBottom(0.5, em)
p(filtered[i].company)
.marginBottom(0.5, em)
p(filtered[i].title)
.fontSize(1.2, em)
.fontWeight("bold")
.marginBottom(0.5, em)
HStack(() => {
p(filtered[i].stars)
.marginRight(0.2, em)
ZStack(() => {
div("★★★★★") // Empty stars (background)
.color("#ccc")
div("★★★★★") // Filled stars (foreground, clipped by width)
.color("#ffa500")
.position("absolute")
.top(0)
.left(0)
.whiteSpace("nowrap")
.overflow("hidden")
.width(percent * 5, em)
})
.display("inline-block")
.position("relative")
.fontSize(1.2, em)
.lineHeight(1)
p(filtered[i].reviews)
.marginLeft(0.2, em)
})
.marginBottom(0.5, em)
p(filtered[i].price)
.fontSize(1.75, em)
.marginBottom(0.5, em)
button("Coming Soon!")
.onClick((finished) => {
if(finished) {
}
})
.onHover(function (hovering) {
if(hovering) {
this.style.backgroundColor = "var(--green)"
} else {
this.style.backgroundColor = ""
}
})
})
.padding(1, em)
.border("1px solid var(--accent2)")
.borderRadius(5, "px")
}
})
.display("grid")
.gridTemplateColumns("repeat(auto-fill, minmax(250px, 1fr))")
.gap(1, em)
} else {
p("No Listings!")
}
})
.onQueryChanged(() => {
console.log("query did change yup")
this.rerender()
})
.height(100, vh)
.paddingLeft(2, em)
.paddingRight(2, em)
.gap(0, em)
.width(100, "%")
}
}
register(MarketGrid)

View File

@@ -1,85 +0,0 @@
class MarketSidebar extends Shadow {
handleChecked(e) {
let checked = e.target.checked
let label = $(`label[for="${e.target.id}"]`).innerText
if(checked) {
window.setQuery(label.toLowerCase(), true)
} else {
window.setQuery(label.toLowerCase(), null)
}
}
render() {
VStack(() => {
p("Make")
HStack(() => {
input()
.attr({
"type": "checkbox",
"id": "hyperia-check"
})
.onChange(this.handleChecked)
label("Hyperia-Made")
.attr({
"for": "hyperia-check"
})
.marginLeft(0.5, em)
})
HStack(() => {
input()
.attr({
"type": "checkbox",
"id": "america-check"
})
.onChange(this.handleChecked)
label("America-Made")
.attr({
"for": "america-check"
})
.marginLeft(0.5, em)
})
p("Condition")
HStack(() => {
input()
.attr({
"type": "checkbox",
"id": "new-check"
})
.onChange(this.handleChecked)
label("New")
.attr({
"for": "new-check"
})
.marginLeft(0.5, em)
})
HStack(() => {
input()
.attr({
"type": "checkbox",
"id": "used-check"
})
.onChange(this.handleChecked)
label("Used")
.attr({
"for": "used-check"
})
.marginLeft(0.5, em)
})
})
.paddingTop(12, vh)
.paddingLeft(3, em)
.paddingRight(3, em)
.gap(1, em)
.minWidth(10, vw)
.userSelect('none')
}
}
register(MarketSidebar)

View File

@@ -1,189 +0,0 @@
import "./MessagesSidebar.js"
import "./MessagesPanel.js"
css(`
messages- {
font-family: 'Bona';
}
messages- input::placeholder {
font-family: 'Bona Nova';
font-size: 0.9em;
color: var(--accent);
}
input[type="checkbox"] {
appearance: none; /* remove default style */
-webkit-appearance: none;
width: 1em;
height: 1em;
border: 1px solid var(--accent);
}
input[type="checkbox"]:checked {
background-color: var(--red);
}
`)
class Messages extends Shadow {
conversations = []
selectedConvoID = null
onConversationSelect(i) {
console.log("convo selected: ", i)
this.selectedConvoID = i
this.$("messagessidebar-").rerender()
this.$("messagespanel-").rerender()
}
getConvoFromID(id) {
for(let i=0; i<this.conversations.length; i++) {
if(this.conversations[i].id === id) {
return this.conversations[i]
}
}
}
render() {
ZStack(() => {
HStack(() => {
MessagesSidebar(this.conversations, this.selectedConvoID, this.onConversationSelect)
VStack(() => {
if(this.getConvoFromID(this.selectedConvoID)) {
MessagesPanel(this.getConvoFromID(this.selectedConvoID).messages)
} else {
MessagesPanel()
}
input("Send Message", "93%")
.paddingVertical(1, em)
.paddingHorizontal(2, em)
.color("var(--accent)")
.background("var(--darkbrown)")
.marginBottom(6, em)
.border("none")
.fontSize(1, em)
.onKeyDown((e) => {
if (e.key === "Enter") {
window.Socket.send({app: "MESSAGES", operation: "SEND", msg: { conversation: `CONVERSATION-${this.selectedConvoID}`, text: e.target.value }})
e.target.value = ""
}
})
})
.gap(1, em)
.width(100, pct)
.horizontalAlign("center")
.verticalAlign("end")
})
.onAppear(async () => {
let res = await global.Socket.send({app: "MESSAGES", operation: "GET"})
if(!res) console.error("failed to get messages")
if(res.msg.length > 0 && this.conversations.length === 0) {
this.conversations = res.msg
this.selectedConvoID = this.conversations[0].id
this.rerender()
}
window.addEventListener("new-message", (e) => {
let convoID = e.detail.conversationID
let messages = e.detail.messages
let convo = this.getConvoFromID(convoID)
convo.messages = messages
this.rerender()
})
})
.width(100, pct)
.height(87, pct)
.x(0).y(13, pct)
VStack(() => {
p("Add Message")
input("enter email...")
.color("var(--accent)")
.onKeyDown(function (e) {
if (e.key === "Enter") {
window.Socket.send({app: "MESSAGES", operation: "ADDCONVERSATION", msg: {email: this.value }})
this.value = ""
}
})
p("x")
.onClick(function (done) {
if(done) {
this.parentElement.style.display = "none"
}
})
.xRight(2, em).y(2, em)
.fontSize(1.4, em)
.cursor("pointer")
})
.gap(1, em)
.verticalAlign("center")
.horizontalAlign("center")
.backgroundColor("black")
.border("1px solid var(--accent)")
.position("fixed")
.x(50, vw).y(50, pct)
.center()
.width(60, vw)
.height(60, pct)
.display("none")
.attr({id: "addPanel"})
HStack(() => {
input("Search messages... (Coming Soon!)", "45vw")
.attr({
"type": "text",
"disabled": "true"
})
.fontSize(1.1, em)
.paddingLeft(1.3, em)
.background("transparent")
.border("0.5px solid var(--divider)")
.outline("none")
.color("var(--accent)")
.opacity(0.5)
.borderRadius(10, px)
.background("grey")
.cursor("not-allowed")
button("+ New Message")
.width(13, em)
.marginLeft(1, em)
.borderRadius(10, px)
.background("transparent")
.border("0.5px solid var(--divider)")
.color("var(--accent)")
.fontFamily("Bona Nova")
.onHover(function (hovering) {
if(hovering) {
this.style.background = "var(--green)"
} else {
this.style.background = "transparent"
}
})
.onClick((done) => {
console.log("click")
if(done) {
this.$("#addPanel").style.display = "flex"
}
console.log(this, "clicked")
})
})
.x(55, vw).y(4, pct)
.position("absolute")
.transform("translateX(-50%)")
})
.boxSizing("border-box")
.height(100, pct)
.width(100, pct)
}
}
register(Messages)

View File

@@ -1,56 +0,0 @@
import "../../components/LoadingCircle.js"
class MessagesPanel extends Shadow {
messages
constructor(messages) {
super()
this.messages = messages
}
render() {
VStack(() => {
if(this.messages) {
for(let i=0; i<this.messages.length; i++) {
let message = this.messages[i]
let fromMe = window.profile.email === message.from.email
VStack(() => {
HStack(() => {
p(message.from.firstName + " " + message.from.lastName)
.fontWeight("bold")
.marginBottom(0.3, em)
p(util.formatTime(message.time))
.opacity(0.2)
.marginLeft(1, em)
})
p(message.text)
})
.paddingVertical(0.5, em)
.marginLeft(fromMe ? 70 : 0, pct)
.paddingRight(fromMe ? 10 : 0, pct)
.marginRight(fromMe ? 0 : 70, pct)
.paddingLeft(fromMe ? 5 : 10, pct)
.background(fromMe ? "var(--brown)" : "var(--green)")
}
} else {
LoadingCircle()
}
})
.onAppear(async () => {
requestAnimationFrame(() => {
this.scrollTop = this.scrollHeight
});
})
.gap(1, em)
.position("relative")
.overflow("scroll")
.height(95, pct)
.width(100, pct)
.paddingTop(2, em)
.paddingBottom(2, em)
.backgroundColor("var(--darkbrown)")
}
}
register(MessagesPanel)

View File

@@ -1,73 +0,0 @@
class MessagesSidebar extends Shadow {
conversations = []
selectedConvoID
onSelect
constructor(conversations, selectedConvoID, onSelect) {
super()
this.conversations = conversations
this.selectedConvoID = selectedConvoID
this.onSelect = onSelect
}
render() {
VStack(() => {
this.conversations.forEach((convo, i) => {
VStack(() => {
HStack(() => {
p(this.makeConvoTitle(convo.between))
.textAlign("left")
.marginLeft(0.5, inches)
.paddingTop(0.2, inches)
.width(100, pct)
.marginTop(0)
.fontSize(1, em)
.fontWeight("bold")
p(util.formatTime(convo.messages.last.time))
.paddingTop(0.2, inches)
.fontSize(0.8, em)
.marginRight(0.1, inches)
.color("var(--divider")
})
.justifyContent("space-between")
.marginBottom(0)
p(convo.messages.last.text)
.fontSize(0.8, em)
.textAlign("left")
.marginLeft(0.5, inches)
.marginBottom(2, em)
.color("var(--divider)")
})
.background(convo.id === this.selectedConvoID ? "var(--darkbrown)" : "")
.onClick(() => {
this.onSelect(i)
})
})
})
.minWidth(15, vw)
.height(100, vh)
.gap(0, em)
}
makeConvoTitle(members) {
let membersString = ""
for(let i=0; i<members.length; i++) {
let member = members[i]
if(member.email === window.profile.email) {
continue;
}
if(members.length > 2) {
membersString += member.firstName
} else {
membersString += member.firstName + " " + member.lastName
}
}
return membersString
}
}
register(MessagesSidebar)

View File

@@ -1,105 +0,0 @@
css(`
people- {
font-family: 'Arial';
}
people- h1 {
font-family: 'Bona';
}
people- p {
color: var(--accent);
}
people- p b {
color: var(--darkbrown);
}
`)
class People extends Shadow {
people = "";
constructor() {
super()
this.people = global.currentNetwork.data.members;
}
render() {
VStack(() => {
h1("People")
.color("rgb(158 136 105)")
.textAlign("center")
if (this.people == "") {
LoadingCircle()
} else if (this.people.length > 0) {
for (let i = 0; i < this.people.length; i++) {
HStack(() => {
HStack(() => { })
.boxSizing("border-box")
.height(3.5, em)
.width(3.5, em)
.padding(0.5, em)
.border("1px solid var(--accent)")
.borderRadius(100, pct)
.background("black")
VStack(() => {
h3(this.people[i].firstName + " " + this.people[i].lastName)
.color("var(--brown)")
.fontSize(1.2, em)
.fontWeight("bold")
.marginVertical(0, em)
p("<b>Member since: </b>" + " " + this.convertDate(this.people[i].created))
})
.verticalAlign("center")
.gap(0.5, em)
})
.height(3.5, em)
.padding(0.75, em)
.gap(1, em)
}
} else {
h2("No Members")
.color("var(--brown)")
.fontWeight("bold")
.marginTop(7.5, em)
.marginBottom(0.5, em)
.textAlign("center")
p("Invite people to this network!")
.textAlign("center")
.color("var(--darkbrown)")
}
})
.position("relative")
.boxSizing("border-box")
.paddingVertical(1, em)
.height(100, pct)
.width(100, pct)
}
convertDate(rawDate) {
const date = rawDate.split("-", 1)[0]; // "01.31.2026
const [mm, dd, yyyy] = date.split(".").map(Number);
const months = [
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
];
const ordinal = (n) => {
const mod100 = n % 100;
if (mod100 >= 11 && mod100 <= 13) return `${n}th`;
switch (n % 10) {
case 1: return `${n}st`;
case 2: return `${n}nd`;
case 3: return `${n}rd`;
default: return `${n}th`;
}
};
return `${months[mm - 1]} ${ordinal(dd)}, ${yyyy}`;
}
}
register(People)

View File

@@ -1,153 +0,0 @@
css(`
tasks- {
font-family: 'Bona';
}
tasks- input::placeholder {
font-family: 'Bona Nova';
font-size: 0.9em;
color: var(--accent);
}
input[type="checkbox"] {
appearance: none; /* remove default style */
-webkit-appearance: none;
width: 1em;
height: 1em;
border: 1px solid var(--accent);
}
input[type="checkbox"]:checked {
background-color: var(--red);
}
`)
class Tasks extends Shadow {
projects = [
{
"title": "Blockcatcher",
"tasks": {}
}
]
columns = [
{
"title": "backlog",
"tasks": {}
}
]
render() {
ZStack(() => {
HStack(() => {
VStack(() => {
h3("Projects")
.marginTop(0)
.marginBottom(1, em)
.marginLeft(0.4, em)
if (this.projects.length >= 1) {
for(let i = 0; i < this.projects.length; i++) {
p(this.projects[i].title)
}
} else {
p("No Projects!")
}
})
.height(100, vh)
.paddingLeft(2, em)
.paddingRight(2, em)
.paddingTop(2, em)
.gap(0, em)
.borderRight("0.5px solid var(--accent2)")
HStack(() => {
if (this.columns.length >= 1) {
for(let i = 0; i < this.columns.length; i++) {
p(this.columns[i].name)
}
} else {
p("No Conversations!")
}
})
.height(100, vh)
.paddingLeft(2, em)
.paddingRight(2, em)
.paddingTop(2, em)
.gap(0, em)
.borderRight("0.5px solid var(--accent2)")
})
.width(100, "%")
.x(0).y(13, vh)
.borderTop("0.5px solid var(--accent2)")
p("0 Items")
.position("absolute")
.x(50, vw).y(50, vh)
.transform("translate(-50%, -50%)")
HStack(() => {
input("Search tasks...", "45vw")
.attr({
"type": "text"
})
.fontSize(1.1, em)
.paddingLeft(1.3, em)
.background("transparent")
.border("0.5px solid var(--accent2)")
.outline("none")
.color("var(--accent)")
.borderRadius(10, px)
button("Search")
.marginLeft(2, em)
.borderRadius(10, px)
.background("transparent")
.border("0.5px solid var(--accent2)")
.color("var(--accent)")
.fontFamily("Bona Nova")
.onHover(function (hovering) {
if(hovering) {
this.style.background = "var(--green)"
} else {
this.style.background = "transparent"
}
})
button("+ New Task")
.width(9, em)
.marginLeft(1, em)
.borderRadius(10, px)
.background("transparent")
.border("0.5px solid var(--accent2)")
.color("var(--accent)")
.fontFamily("Bona Nova")
.onHover(function (hovering) {
if(hovering) {
this.style.background = "var(--green)"
} else {
this.style.background = "transparent"
}
})
.onClick((clicking) => {
console.log(this, "clicked")
})
})
.x(55, vw).y(4, vh)
.position("absolute")
.transform("translateX(-50%)")
})
.width(100, "%")
.height(100, "%")
}
connectedCallback() {
// Optional additional logic
}
}
register(Tasks)

View File

@@ -1,72 +0,0 @@
import { Haptics, ImpactStyle } from '@capacitor/haptics';
import util from "../util.js"
class AppMenu extends Shadow {
selected = ""
apps = global.currentNetwork.apps.filter(app => (app !== "Settings" && app !== "Website"))
darkMode = window.matchMedia('(prefers-color-scheme: dark)').matches
getImageURL(appName) {
let imgUrl = `${util.HOST}/apps/${appName}/icons/${appName}`
if(this.darkMode) {
imgUrl += "light"
}
imgUrl += ".svg"
imgUrl = imgUrl.toLowerCase()
return imgUrl
}
onNewSelection() {
this.$$("img").forEach((image) => {
image.style.borderBottom = "1px solid transparent"
const appName = image.attributes.app.value
if (appName === global.currentApp()) {
image.style.borderBottom = "1px solid var(--text)"
}
image.src = this.getImageURL(appName)
})
}
render() {
let apps = this.apps
let appCount = apps.length
let horizontalMargin = {
1: 50,
2: 10,
3: 2,
4: 1.5,
5: 0.5
}[appCount] ?? 4
HStack(() => {
for(let i = 0; i < apps.length; i++) {
let app = apps[i]
img(this.getImageURL(app), "1.3em")
.attr({app: app})
.padding(0.5, em)
.borderBottom(global.currentApp() === app ? "1px solid var(--text)" : "1px solid transparent")
.onTouch(async (done, e) => {
if(done) {
global.openApp(app)
this.onNewSelection()
await Haptics.impact({ style: ImpactStyle.Light });
}
})
}
})
.display("grid")
.gridTemplateColumns(`repeat(${apps.filter(app => app !== "Settings").length}, 1fr)`)
.placeItems("center")
.borderTop("0.5px solid var(--divider)")
.height("auto")
.zIndex(1)
.paddingTop(0.5, em)
.paddingBottom(2, em)
.width(100, vw)
.boxSizing("border-box")
}
}
register(AppMenu)

View File

@@ -1,30 +0,0 @@
import util from "../util.js"
class AppWindow extends Shadow {
render() {
ZStack(() => {
let app = global.currentApp()
if(window[app]) {
window[app]()
} else {
this.getCustomApp(app)
}
})
.height(100, pct)
.overflowY("scroll")
.onNavigate(() => {
this.rerender()
})
}
async getCustomApp(app) {
await import(`${util.HOST}/apps/${app.toLowerCase()}/${app.toLowerCase()}.js`);
if(window[app]) {
this.rerender()
} else {
console.error("Could not get app: ", app)
}
}
}
register(AppWindow)

View File

@@ -1,37 +0,0 @@
import "./AppWindow.js"
import "../Profile/Profile.js"
import "./TopBar.js"
class AppWindowContainer extends Shadow {
render() {
ZStack(() => {
VStack(() => {
TopBar()
AppWindow()
})
.width(100, pct)
.gap(0)
Profile()
.zIndex(3)
})
.height(100, pct)
.overflowY("hidden")
.display("flex")
.position("relative")
}
openProfile() {
this.$("profile-").top(20, px)
this.$("profile-").pointerEvents("auto")
}
closeProfile() {
this.$("profile-").top(100, vh)
this.$("profile-").pointerEvents("none")
}
}
register(AppWindowContainer)

View File

@@ -1,127 +0,0 @@
import util from "../util"
import "./Toggle.js"
class Sidebar extends Shadow {
SIDEBAR_WIDTH
constructor(width) {
super()
this.SIDEBAR_WIDTH = width
}
SidebarItem(text) {
return p(text)
.fontSize(1.2, em)
.fontWeight("bold")
.color("var(--headertext)")
.fontFamily("Arial")
.marginLeft(3, em)
.marginTop(2, em)
.onTap(function (done) {
if (done) {
if (this.innerText === "Logout") {
global.onLogout()
$("home-").closeSidebar();
return
}
}
})
}
render() {
VStack(() => {
HStack(() => {
if (global.profile.image_path) {
img(`${util.HOST}${global.profile.image_path}`, "10em", "10em")
.borderRadius(100, pct)
}
})
.boxSizing("border-box")
.height(10, em)
.width(10, em)
.border("1px solid var(--accent)")
.borderRadius(100, pct)
.background("var(--darkaccent)")
.alignSelf("center")
.onClick((done) => {
if(done)
this.openProfile()
})
h2(global.profile.first_name + " " + global.profile.last_name)
.color("var(--headertext")
.textAlign("center")
.marginVertical(0.25, em)
.paddingBottom(0.5, em)
.textAlign("center")
.alignSelf("center")
.overflowWrap("break-word")
.wordBreak("break-word")
.width(100, pct)
.borderBottom("2px solid var(--divider)")
.onClick((done) => {
if(done)
this.openProfile()
})
.paddingBottom(1, em)
this.SidebarItem("Logout")
VStack(() => {
Toggle("Enable Push Notifications")
.marginLeft(1, em)
button("Delete Account")
.fontSize(0.9, em)
.marginBottom(2, em)
.background("var(--darkred)")
.paddingVertical(1, em)
.border("none")
.outline("1px solid var(--divider)")
.color("var(--text)")
.onTap((done) => this.deleteAccount())
})
.marginTop("auto")
.gap(2, em)
})
.gap(1, em)
.paddingTop(15, vh)
.paddingHorizontal(1, em)
.height(105, vh)
.top(-5, vh)
.minWidth(0)
.boxSizing("border-box")
.width(this.SIDEBAR_WIDTH, px)
.borderLeft("1px solid var(--divider)")
.color("var(--text)")
.position("fixed")
.background("var(--sidebar)")
}
openProfile() {
$("appwindowcontainer-").openProfile()
$("home-").closeSidebar();
}
async deleteAccount() {
try {
const res = await util.authFetch(`${util.HOST}/auth/delete`, {
method: "DELETE",
credentials: "include",
headers: {
"X-Client": "mobile",
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify({ memberId: global.profile.id })
});
if (!res.ok) return;
global.onLogout()
} catch (err) {
console.error(err)
}
}
}
register(Sidebar)

View File

@@ -1,50 +0,0 @@
css(`
.toggle-input {
appearance: none;
width: 44px;
height: 24px;
background: #ccc;
border-radius: 12px;
position: relative;
cursor: pointer;
transition: background 0.2s;
}
.toggle-input::after {
content: '';
position: absolute;
width: 20px;
height: 20px;
background: white;
border-radius: 50%;
top: 2px;
left: 2px;
transition: left 0.2s;
}
.toggle-input:checked {
background: var(--darkred);
}
.toggle-input:checked::after {
left: 22px;
}
`)
class Toggle extends Shadow {
render() {
HStack(() => {
input("", "44px", "24px")
.attr({ type: "checkbox", checked: global.profile.preferences.notifications ? "" : null, class: "toggle-input"})
.onChange(async (e) => {
await server.updateNotificationPreferences(global.profile.id, e.target.checked)
})
p("Enable Push Notifications")
.color("var(--text)")
})
.verticalAlign("center")
.gap(10, px)
}
}
register(Toggle)

View File

@@ -1,53 +0,0 @@
import util from "../util.js"
class TopBar extends Shadow {
render() {
HStack(() => {
if (global.currentNetwork.logo) {
img(`${util.HOST}/db/images/${global.currentNetwork.logo}`, "2.5em", "2.5em")
.borderRadius("50", pct)
.objectFit("cover")
.padding(0.3, em)
.background("var(--accent)")
.onTouch(function (start) {
if(start) {
this.style.scale = "0.8"
} else if(start === false) {
this.style.scale = ""
if (!$("home-").sidebarOpen) {
$("home-").openSidebar()
}
}
})
} else {
HStack(() => { })
.height(2.5, em)
.width(2.5, em)
.padding(0.3, em)
.background("var(--accent)")
.borderRadius("50", pct)
}
p()
.state("app", function () {
this.innerText = global.currentApp()
})
.color("var(--headertext)")
.textAlign("center")
.fontFamily("Arial")
.fontSize("clamp(0.8rem, 40cqw, 7cqw)")
.fontWeight("bold")
})
.containerType("inline-size")
.paddingLeft(1, em)
.paddingBottom(1.5, em)
.verticalAlign("center")
.gap(0.5, em)
.marginTop(4, em)
.onNavigate(() => {
this.$("p").attr({app: global.currentApp()})
})
}
}
register(TopBar)

View File

@@ -9,23 +9,125 @@
/>
<meta name="format-detection" content="telephone=no" />
<meta name="msapplication-tap-highlight" content="no" />
<script
type="module"
src="https://unpkg.com/@ionic/pwa-elements@latest/dist/ionicpwaelements/ionicpwaelements.esm.js"
></script>
<script
nomodule
src="https://unpkg.com/@ionic/pwa-elements@latest/dist/ionicpwaelements/ionicpwaelements.js"
></script>
<link rel="icon" type="image/x-icon" href="./_/icons/columnwhite.svg" />
<link rel="manifest" href="./manifest.json" />
<link rel="stylesheet" href="./_/code/shared.css" />
<script src="/_/code/quill.js"></script>
<script type="module" src="./index.js"></script>
<link rel="stylesheet" href="" />
<script>window.config = { UI: 'https://frm.so', SERVER: 'https://frm.so' }</script>
<script type="module">
await import('./mobileutil.js')
function appendScript(src, isModule = false) {
return new Promise((resolve, reject) => {
const s = document.createElement('script')
s.src = src
s.crossOrigin = "anonymous"
if (isModule) s.type = 'module'
s.onload = resolve
s.onerror = reject
document.head.appendChild(s)
})
}
function appendStylesheet(href, { replaceExisting = false } = {}) {
return new Promise((resolve, reject) => {
if (replaceExisting) {
document.querySelector('link[rel="stylesheet"]')?.remove();
}
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = href;
link.onload = resolve;
link.onerror = reject;
document.head.appendChild(link);
});
}
try {
await appendStylesheet(`${window.config.UI}/_/code/shared.css`, { replaceExisting: true });
await appendScript(window.config.UI + '/_/code/quill.js')
await appendScript(window.config.UI + '/83947261/index.js', true)
} catch (e) {
document.body.innerHTML = `
<style>
#ptr-screen {
position: fixed; inset: 0;
display: flex; flex-direction: column;
align-items: center; justify-content: center;
font-family: sans-serif; text-align: center;
padding: 2rem; touch-action: none;
transition: transform 0.2s ease;
color: var(--text);
}
#ptr-icon {
font-size: 2rem; margin-bottom: 1rem;
transition: transform 0.2s ease, opacity 0.2s ease;
opacity: 0.4;
}
#ptr-label {
font-size: 0.9rem; opacity: 0.5;
margin-top: 0.5rem;
}
#ptr-indicator {
color: var(--text);
position: fixed; top: 5vh; left: 0; right: 0;
display: flex; align-items: center; justify-content: center;
padding-top: env(safe-area-inset-top);
height: 0; overflow: hidden;
transition: height 0.1s ease;
font-size: 0.8rem; opacity: 0.6; gap: 0.4rem;
}
@keyframes spin { to { transform: rotate(360deg) } }
.spinning { animation: spin 0.6s linear infinite }
</style>
<div id="ptr-indicator">
<span id="ptr-arrow">↓</span>
<span id="ptr-hint">Pull to retry</span>
</div>
<div id="ptr-screen">
<div id="ptr-icon">⚠️</div>
<p style="margin:0;font-size:1.1rem;font-weight:600">No connection</p>
<p id="ptr-label">Could not reach the server.<br>Pull down to try again.</p>
</div>
`
const THRESHOLD = 90
let startY = 0, dragging = false
document.addEventListener('touchstart', e => {
startY = e.touches[0].clientY
dragging = true
})
document.addEventListener('touchmove', e => {
if (!dragging) return
const dy = Math.max(0, e.touches[0].clientY - startY)
const pull = Math.min(dy, THRESHOLD * 1.5)
const progress = Math.min(pull / THRESHOLD, 1)
document.getElementById('ptr-screen').style.transform = `translateY(${pull * 0.4}px)`
document.getElementById('ptr-indicator').style.height = (pull * 0.6) + 'px'
document.getElementById('ptr-arrow').style.transform = `rotate(${progress * 180}deg)`
document.getElementById('ptr-hint').textContent = progress >= 1 ? 'Release to retry' : 'Pull to retry'
document.getElementById('ptr-icon').style.opacity = 0.4 + progress * 0.6
})
document.addEventListener('touchend', e => {
if (!dragging) return
dragging = false
const dy = e.changedTouches[0].clientY - startY
if (dy >= THRESHOLD) {
document.getElementById('ptr-arrow').textContent = '↻'
document.getElementById('ptr-arrow').classList.add('spinning')
document.getElementById('ptr-hint').textContent = 'Retrying…'
setTimeout(() => location.reload(), 400)
} else {
document.getElementById('ptr-screen').style.transform = ''
document.getElementById('ptr-indicator').style.height = '0'
}
})
}
</script>
<meta name="theme-color" content="#31d53d" />
</head>
<body>
</body>
</html>
</html>

View File

@@ -1,211 +0,0 @@
import { PushNotifications } from '@capacitor/push-notifications';
import Socket from "/_/code/ws/Socket.js"
import "./Home/Home.js"
import "./Home/AuthPage/AuthPage.js"
import "./Home/ConnectionError.js"
import util from "./util.js"
const env = import.meta.env
let Global = class {
Socket = new Socket()
profile = null
currentNetwork = ""
lastApp = ""
util = util
currentApp() {
const pathname = window.location.pathname;
const segments = pathname.split('/').filter(Boolean)
const secondSegment = segments[1] || ""
const capitalized = secondSegment.charAt(0).toUpperCase() + secondSegment.slice(1);
return capitalized
}
openApp = function(appName) {
const appUrl = appName.charAt(0).toLowerCase() + appName.slice(1);
let parts = window.location.pathname.split('/').filter(Boolean);
let newPath = "/" + parts[0] + "/" + appUrl
window.navigateTo(newPath)
const event = new CustomEvent('appchange', {
detail: { name: appName }
});
window.dispatchEvent(event)
}
onNavigate = async () => {
if(!global.profile) return
let selectedNetwork = this.networkFromPath()
if(!selectedNetwork) {
if (!this.currentNetwork || this.currentNetwork === this.profile) {
let path = `/${this.getDefaultNetworkName()}/${this.getDefaultAppName()}`
history.replaceState({}, '', path)
}
} else if(!this.currentApp()) {
if(this.currentNetwork === window.profile) {
history.replaceState({}, '', `${window.location.pathname}/${window.profile.apps[0]}`)
} else {
history.replaceState({}, '', `${window.location.pathname}/${this.getDefaultAppName()}`)
}
}
selectedNetwork = this.networkFromPath()
let networkChanged = this.currentNetwork !== selectedNetwork
let appChanged = this.currentApp() !== this.lastApp
if(appChanged) {
this.lastApp = this.currentApp()
}
if(networkChanged) {
this.currentNetwork = selectedNetwork
const event = new CustomEvent('networkchange', {
detail: { name: this.currentNetwork }
});
window.dispatchEvent(event)
}
if(appChanged && !networkChanged) {
const event = new CustomEvent('appchange', {
detail: { name: this.currentApp() }
});
window.dispatchEvent(event)
}
document.title = (this.currentNetwork === this.profile) ? "Forum" : `${this.currentNetwork.abbreviation} | Forum`
}
setCurrentNetworkAndApp() {
this.currentNetwork = this.networkFromPath()
}
getDefaultNetworkName() {
let defaultNetwork = this.profile.networks[0]
if (!defaultNetwork) { return "my"; }
return defaultNetwork.abbreviation
}
getDefaultAppName() {
let defaultNetwork = this.profile.networks[0]
if (!defaultNetwork) { return this.profile.apps[0].toLowerCase(); }
return defaultNetwork.apps[0].toLowerCase()
}
networkFromPath = function () {
const pathname = window.location.pathname;
const firstSegment = pathname.split('/').filter(Boolean)[0] || '';
if(firstSegment === "my") {
return this.profile
} else {
let networks = this.profile.networks
for(let i = 0; i < networks.length; i++) {
let network = networks[i]
if(network.abbreviation === firstSegment) {
return network
}
}
}
}
async getProfile() {
try {
const res = await util.authFetch(`${util.HOST}/auth/profile`, {
method: "GET",
credentials: "include",
headers: {
"Accept": "application/json"
}
});
if(res.status === 401) {
return res.status
}
if (!res.ok) return res.status;
const profile = await res.json();
console.log("getProfile: ", profile);
this.profile = profile
return 200;
} catch (err) { // Network error / Error reaching server
console.error(err);
return 500;
}
}
async renderHome() {
location.reload()
}
async onLogout() {
await util.removeAuthToken()
await fetch(`${util.HOST}/auth/signout`, {
method: "GET",
credentials: "include"
});
this.profile = null
location.reload()
}
async setupPushNotifications() {
if (!Capacitor.isNativePlatform()) return;
PushNotifications.addListener('registration', async (token) => {
console.log('Device token:', token.value)
const stored = localStorage.getItem('deviceToken')
if (stored === token.value) return;
console.log("new push token")
await server.updatePushToken(token.value, global.profile.id, env.MODE)
localStorage.setItem('deviceToken', token.value)
});
PushNotifications.addListener('registrationError', (error) => {
console.error('Registration error:', JSON.stringify(error))
});
PushNotifications.addListener('pushNotificationReceived', (notification) => {
console.log('Notification received:', notification)
});
PushNotifications.addListener('pushNotificationActionPerformed', (action) => {
console.log('Notification tapped:', action.notification)
// navigate somewhere based on action.notification.data
});
const permission = await PushNotifications.requestPermissions();
if (permission.receive === 'granted') {
await PushNotifications.register();
console.log('after register:')
}
}
async init() {
try {
const module = await import(`${util.HOST}/@server/server.js`);
window.server = module.default;
} catch(E) {
console.error(E)
}
window.addEventListener("navigate", this.onNavigate)
this.getProfile().then(async (status) => {
if (status === 401) {
navigateTo("/")
AuthPage()
} else if(status === 500) {
ConnectionError()
} else {
await this.Socket.init()
await this.setupPushNotifications()
await this.onNavigate()
Home()
}
})
}
constructor() {
this.init()
}
}
window.global = new Global()

41
src/mobileutil.js Normal file
View File

@@ -0,0 +1,41 @@
import { PushNotifications } from '@capacitor/push-notifications';
import { Preferences } from '@capacitor/preferences';
import { Filesystem, Directory } from '@capacitor/filesystem';
import { Haptics, ImpactStyle } from '@capacitor/haptics';
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
import { Geolocation } from '@capacitor/geolocation';
import { SplashScreen } from '@capacitor/splash-screen';
window.capacitor = {
Preferences,
PushNotifications,
Filesystem,
Directory,
Haptics,
ImpactStyle,
Camera,
CameraResultType,
CameraSource,
Geolocation,
SplashScreen,
}
window.mobileUtil = class mobileUtil {
static async authFetch(url, options = {}) {
const { value: token } = await Preferences.get({ key: 'auth_token' });
return fetch(url, {
...options,
headers: {
...options.headers,
'Authorization': `Bearer ${token}`,
'X-Client': 'mobile'
}
});
}
static async removeAuthToken() {
await Preferences.remove({ key: 'auth_token'})
}
}

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +0,0 @@
<svg width="28" height="32" viewBox="0 0 28 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.52366 0.0493342C4.88415 0.328928 1.12711 1.09781 0.253382 1.93659L0 2.18124V3.45688V4.73253L0.244645 4.9597C0.541713 5.23929 0.917417 5.43152 1.69504 5.69363C2.42023 5.94702 2.60372 5.96449 2.44645 5.77227C1.99211 5.22182 3.27649 4.584 5.7142 4.16461C8.0558 3.75395 9.35765 3.67532 13.5428 3.67532C17.728 3.67532 19.0299 3.75395 21.3715 4.16461C23.8354 4.584 25.0935 5.22182 24.6305 5.78974C24.5169 5.9208 24.5344 5.92954 24.7877 5.87712C25.3382 5.77227 26.4915 5.26551 26.7886 5.01212L27.0856 4.75001V3.45688V2.16376L26.7886 1.90164C25.9498 1.16771 22.8743 0.4862 18.7852 0.136707C17.3523 0.00564766 11.1401 -0.0467762 9.52366 0.0493342Z" fill="black"/>
<path d="M10.6246 5.30045C8.06453 5.44899 5.65304 5.82469 4.49971 6.26156C3.80073 6.52367 3.49492 6.83822 3.49492 7.27508V7.62458L4.0978 7.61584C4.63077 7.6071 4.73562 7.63331 4.93658 7.82553C5.06764 7.94786 5.20743 8.11386 5.25986 8.20997C5.31228 8.31482 5.33849 11.3292 5.32976 16.79L5.32102 25.2128H5.76662H6.20349V16.423C6.20349 6.60231 6.16854 7.15276 6.79762 6.89064C7.18207 6.73337 7.75873 6.80327 8.06453 7.03918C8.58877 7.45857 8.56256 6.82948 8.56256 18.1268V28.4456H9.17417H9.78578V17.8734C9.78578 11.4428 9.81199 7.24013 9.86442 7.14402C10.0741 6.75958 10.3974 6.56736 10.9216 6.53241C11.5158 6.48873 11.9526 6.68968 12.1361 7.0916C12.2148 7.26635 12.241 10.1671 12.2322 19.4549V31.591H13.5865H14.9408V19.4636C14.9408 7.59836 14.9408 7.33624 15.1155 7.06539C15.6136 6.24408 16.9853 6.34893 17.3436 7.24013C17.4571 7.52846 17.4746 8.89148 17.4746 18.0132V28.4543L18.0687 28.4281L18.6541 28.4019L18.6279 18.2229C18.6017 11.2069 18.6279 7.94786 18.6891 7.7469C18.9774 6.82948 20.2443 6.48873 20.7861 7.18771C20.9695 7.41488 20.9695 7.4673 20.9695 16.3095V25.2128H21.4064H21.8433V16.8424C21.8433 8.708 21.852 8.47209 22.018 8.20124C22.2714 7.77311 22.5597 7.63331 23.1189 7.64205H23.6169L23.5645 7.2314C23.5296 6.94307 23.4597 6.76832 23.2937 6.63726C22.1403 5.63247 16.0155 4.99465 10.6246 5.30045Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -1,9 +0,0 @@
<svg width="306" height="315" viewBox="0 0 306 315" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M257.568 6.10352e-05H47.9351V28.2306H257.568V6.10352e-05Z" fill="#FFD5A4"/>
<path d="M207.362 174.274C205.545 172.318 203.134 171.234 200.549 171.234C195.203 171.234 190.836 176.021 190.836 181.891V314.449H210.262V181.891C210.262 178.991 209.249 176.301 207.362 174.274Z" fill="#FFD5A4"/>
<path d="M233.844 314.448V121.795C229.581 123.472 224.97 124.416 220.148 124.416H85.3542C80.5326 124.416 75.9207 123.472 71.6582 121.795V314.448H90.0011V181.89C90.0011 173.12 96.7093 165.993 104.955 165.993C109.008 165.993 112.781 167.67 115.611 170.71C118.371 173.679 119.909 177.662 119.909 181.89V314.448H137.797V156.524C137.797 147.755 144.506 140.627 152.751 140.627C156.769 140.627 160.542 142.304 163.407 145.309C166.203 148.314 167.705 152.297 167.705 156.524V314.448H185.594V181.89C185.594 173.12 192.302 165.993 200.547 165.993C204.6 165.993 208.374 167.67 211.204 170.71C213.964 173.679 215.501 177.662 215.501 181.89V314.448H233.844Z" fill="#FFD5A4"/>
<path d="M159.562 148.909C157.71 146.953 155.3 145.87 152.749 145.87C147.403 145.87 143.036 150.656 143.036 156.526V314.449H162.462V156.526C162.462 153.626 161.449 150.936 159.562 148.909Z" fill="#FFD5A4"/>
<path d="M111.769 174.274C109.952 172.318 107.542 171.234 104.956 171.234C99.6105 171.234 95.2432 176.021 95.2432 181.891V314.449H114.669V181.891C114.669 178.991 113.656 176.301 111.769 174.274Z" fill="#FFD5A4"/>
<path d="M245.831 106.423C233.916 98.9114 225.95 85.6696 225.95 70.611C225.95 70.4363 225.95 70.2965 225.95 70.1218H79.5569C79.5569 70.1218 79.5569 70.4363 79.5569 70.611C79.5569 85.7045 71.5909 98.9463 59.6768 106.423C65.5814 114.145 74.8751 119.176 85.3568 119.176H220.151C230.632 119.176 239.926 114.145 245.831 106.423Z" fill="#FFD5A4"/>
<path d="M37.1399 107.716C57.6141 107.716 74.2799 91.0507 74.2799 70.6115C74.2799 70.4368 74.2799 70.297 74.2799 70.1223H34.834C33.4015 70.1223 32.2136 68.9344 32.2136 67.5019C32.2136 66.0694 33.4015 64.8815 34.834 64.8815H270.671C272.103 64.8815 273.291 66.0694 273.291 67.5019C273.291 68.9344 272.103 70.1223 270.671 70.1223H231.225C231.225 70.1223 231.225 70.4368 231.225 70.6115C231.225 91.0856 247.891 107.716 268.365 107.716C288.839 107.716 305.505 91.0507 305.505 70.6115C305.505 50.1723 288.839 33.4716 268.365 33.4716H37.1399C16.6658 33.4716 0 50.1374 0 70.6115C0 91.0856 16.6658 107.716 37.1399 107.716Z" fill="#FFD5A4"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -1,3 +0,0 @@
<svg width="92" height="73" viewBox="0 0 92 73" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M34.7556 0C34.3767 0 34.0134 0.15234 33.7439 0.42188C33.4782 0.69141 33.3259 1.05469 33.3298 1.43358V5.24998H24.6189C21.2712 5.24998 18.5251 7.99608 18.5251 11.3477V21.1758C15.5368 34.2268 9.5993 46.4138 1.1541 56.8008C1.14629 56.8086 1.13848 56.8203 1.13457 56.832L0.736131 57.3477C-1.09197 59.7305 0.704881 63.3593 3.70883 63.3593H18.5248V65.2343C18.5248 69.1445 21.7201 72.3438 25.6303 72.3438H84.3183C88.2285 72.3438 91.4277 69.1445 91.4277 65.2343V21.4574V21.3988V19.3246V19.2894V11.348C91.4277 7.9964 88.6816 5.2542 85.33 5.2542H76.6308V1.4339C76.6308 1.05499 76.4824 0.68781 76.2129 0.4183C75.9433 0.14877 75.5761 0.000329971 75.1973 0.000329971C74.8184 0.000329971 74.4551 0.15267 74.1895 0.42221C73.9199 0.69174 73.7715 1.05502 73.7715 1.43391V5.25421L36.1895 5.2503V1.4339C36.1895 1.05499 36.0411 0.687814 35.7715 0.418303C35.502 0.148773 35.1344 0 34.7556 0ZM24.6186 8.1094H33.3295V11.9375C33.3334 12.7266 33.9701 13.3594 34.7553 13.3633C35.1342 13.3633 35.4975 13.2149 35.767 12.9492C36.0365 12.6797 36.1888 12.3164 36.1888 11.9375V8.10944H73.7748V11.9375H73.7709C73.7748 12.7227 74.4115 13.3594 75.1967 13.3633C75.5756 13.3633 75.9389 13.2149 76.2084 12.9493C76.478 12.6798 76.6264 12.3165 76.6303 11.9376V8.10948H85.3295C87.1342 8.10948 88.5678 9.53918 88.5678 11.3478V19.965H21.3798V19.3634V19.2892V11.3478C21.3798 9.5431 22.8139 8.1133 24.6186 8.1094ZM21.0874 22.8204H88.1774C85.0797 35.2464 79.2985 46.8514 71.2084 56.8004C71.1966 56.8082 71.1888 56.8199 71.1771 56.8317L70.7865 57.3473C69.2631 59.3356 66.9076 60.5035 64.4037 60.5035H19.9627C19.9588 60.4996 19.951 60.4996 19.9471 60.4996C19.9432 60.4996 19.9353 60.4996 19.9314 60.5035H3.70844C2.88813 60.5035 2.51314 59.7379 3.00922 59.0894L3.37641 58.605L3.38813 58.5855C11.8881 48.1285 17.9354 35.9104 21.0874 22.8204ZM88.5644 31.5274V65.2344C88.5644 67.6016 86.6816 69.4961 84.3144 69.4961H25.6304C23.2632 69.4961 21.3804 67.6016 21.3804 65.2344V63.3594H64.4074C67.798 63.3594 70.9933 61.7774 73.0558 59.086L73.423 58.6016C80.0127 50.5 85.1264 41.3354 88.5644 31.5274Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -1,3 +0,0 @@
<svg width="88" height="69" viewBox="0 0 88 69" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M33.4525 0C33.0878 0 32.7382 0.145299 32.4788 0.40238C32.2231 0.659453 32.0765 1.00594 32.0802 1.36732V5.00732H23.6959C20.4737 5.00732 17.8306 7.6265 17.8306 10.8232V20.197C14.9543 32.6448 9.23941 44.2685 1.11083 54.1754C1.10331 54.1829 1.09579 54.1941 1.09203 54.2052L0.708533 54.697C-1.05103 56.9697 0.678454 60.4309 3.56978 60.4309H17.8303V62.2192C17.8303 65.9487 20.9058 69 24.6694 69H81.1571C84.9207 69 88 65.9487 88 62.2192V20.4656V20.4097V18.4314V18.3978V10.8235C88 7.6268 85.3568 5.01135 82.1309 5.01135H73.7579V1.36762C73.7579 1.00623 73.615 0.656019 73.3555 0.398966C73.0961 0.141894 72.7427 0.00031472 72.378 0.00031472C72.0133 0.00031472 71.6637 0.145613 71.408 0.402695C71.1486 0.659767 71.0057 1.00626 71.0057 1.36763V5.01136L34.8327 5.00763V1.36763C34.8327 1.00623 34.6898 0.656023 34.4304 0.398969C34.171 0.141897 33.8172 0 33.4525 0ZM23.6956 7.73458H32.0799V11.3857C32.0837 12.1383 32.6965 12.7419 33.4522 12.7456C33.817 12.7456 34.1666 12.6041 34.426 12.3507C34.6854 12.0937 34.8321 11.7472 34.8321 11.3858V7.73462H71.0089V11.3858H71.0052C71.0089 12.1347 71.6218 12.742 72.3775 12.7457C72.7422 12.7457 73.0919 12.6041 73.3513 12.3508C73.6107 12.0937 73.7536 11.7472 73.7573 11.3858V7.73466H82.1304C83.8674 7.73466 85.2473 9.09828 85.2473 10.8233V19.0422H20.5783V18.4684V18.3977V10.8233C20.5783 9.10202 21.9585 7.7383 23.6956 7.73458ZM20.2968 21.7656H84.8715C81.8899 33.6173 76.3255 44.6859 68.5387 54.1751C68.5274 54.1825 68.5199 54.1937 68.5086 54.2049L68.1326 54.6967C66.6663 56.5931 64.3991 57.707 61.9891 57.707H19.2143C19.2105 57.7033 19.203 57.7033 19.1992 57.7033C19.1955 57.7033 19.1879 57.7033 19.1842 57.707H3.56941C2.77985 57.707 2.41892 56.9768 2.8964 56.3582L3.24983 55.8963L3.26111 55.8776C11.4424 45.904 17.2629 34.2506 20.2968 21.7656ZM85.244 30.0702V62.2192C85.244 64.477 83.4318 66.284 81.1533 66.284H24.6695C22.391 66.284 20.5788 64.477 20.5788 62.2192V60.4309H61.9927C65.2561 60.4309 68.3316 58.922 70.3168 56.355L70.6702 55.893C77.013 48.1659 81.9349 39.4249 85.244 30.0702Z" fill="#FFE9C8"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -1,3 +0,0 @@
<svg width="89" height="70" viewBox="0 0 89 70" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M72.8799 0.25C73.3087 0.25 73.7257 0.416994 74.0332 0.72168C74.3407 1.02634 74.5097 1.44034 74.5098 1.86719V5.26172H82.6328C85.9944 5.26172 88.7518 7.98625 88.752 11.3232V62.7188C88.752 66.5884 85.5587 69.75 81.6592 69.75H25.1709C21.2714 69.7497 18.082 66.5881 18.082 62.7188V61.1807H4.07129C0.977827 61.1803 -0.877206 57.485 1.0127 55.0439L1.01367 55.043L1.38574 54.5645C1.39618 54.5468 1.40769 54.5308 1.41992 54.5166L2.17188 53.5859C9.87157 43.9211 15.3033 32.6784 18.083 20.665V11.3232C18.083 7.98644 20.84 5.25781 24.1982 5.25781H32.332V1.86719C32.3283 1.43709 32.5035 1.02844 32.8037 0.726562L32.8047 0.724609C33.1103 0.421755 33.523 0.250102 33.9541 0.25C34.383 0.25 34.801 0.417052 35.1084 0.72168C35.4158 1.02632 35.5848 1.44043 35.585 1.86719V5.25781L71.2578 5.26074V1.86719C71.2579 1.44034 71.4264 1.03058 71.7324 0.726562L71.8516 0.618164C72.1394 0.381566 72.503 0.250021 72.8799 0.25ZM85.4961 31.9873C82.1901 40.8638 77.4261 49.1646 71.3701 56.5439L71.3711 56.5449L71.0176 57.0068L71.0166 57.0078C68.9839 59.6362 65.8347 61.1807 62.4941 61.1807H21.3311V62.7197C21.3313 64.838 23.0304 66.5342 25.1719 66.5342H81.6553C83.7967 66.5342 85.4958 64.838 85.4961 62.7197V31.9873ZM20.9941 22.5156C17.9401 34.9588 12.1246 46.5722 3.96777 56.5205L3.96582 56.5254L3.95898 56.5371L3.9502 56.5479L3.59668 57.0098V57.0107C3.40752 57.2558 3.40294 57.4916 3.4834 57.6533C3.56401 57.8154 3.75623 57.957 4.07129 57.957H19.6533C19.6787 57.9529 19.7005 57.9531 19.7012 57.9531C19.7016 57.9531 19.7235 57.9529 19.749 57.957H62.4912C64.8238 57.957 67.0177 56.8788 68.4365 55.0439L68.8115 54.5527L68.8223 54.5391L68.835 54.5273L68.8359 54.5264C68.8373 54.5249 68.8394 54.5221 68.8418 54.5195C68.8444 54.5167 68.8488 54.5135 68.8535 54.5088C76.5454 45.133 82.0603 34.211 85.0508 22.5156H20.9941ZM23.9014 8.5C22.4425 8.64669 21.3301 9.84168 21.3301 11.3232V19.292H85.499V11.3232C85.499 9.73882 84.2339 8.48461 82.6328 8.48438H74.5098V11.8887C74.5053 12.3144 74.3363 12.724 74.0293 13.0283L74.0283 13.0293C73.7219 13.3286 73.3091 13.496 72.8799 13.4961H72.8779C71.9873 13.4915 71.2613 12.7747 71.2568 11.8867L71.2559 11.6357H71.2607V8.48438H35.584V11.8857C35.584 12.3152 35.4093 12.7253 35.1035 13.0283L35.1025 13.0293C34.796 13.3287 34.3835 13.4961 33.9541 13.4961H33.9531C33.0628 13.4917 32.3365 12.779 32.332 11.8867V8.48438H24.1982L23.9014 8.5Z" fill="#BD2D2D" stroke="#FFD5A4" stroke-width="0.5"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.1 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.1 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100px" height="100px"><path d="M 17 21 A 1.0001 1.0001 0 0 0 16 22 L 16 32 A 1.0001 1.0001 0 0 0 17 33 L 83 33 A 1.0001 1.0001 0 0 0 84 32 L 84 22 A 1.0001 1.0001 0 0 0 83 21 L 17 21 z M 18 23 L 82 23 L 82 31 L 18 31 L 18 29 L 73.5 29 A 0.50005 0.50005 0 1 0 73.5 28 L 18 28 L 18 23 z M 76.5 28 A 0.50005 0.50005 0 1 0 76.5 29 L 78.5 29 A 0.50005 0.50005 0 1 0 78.5 28 L 76.5 28 z M 17 44 A 1.0001 1.0001 0 0 0 16 45 L 16 55 A 1.0001 1.0001 0 0 0 17 56 L 83 56 A 1.0001 1.0001 0 0 0 84 55 L 84 45 A 1.0001 1.0001 0 0 0 83 44 L 17 44 z M 18 46 L 82 46 L 82 54 L 18 54 L 18 46 z M 22.5 51 A 0.50005 0.50005 0 1 0 22.5 52 L 67.5 52 A 0.50005 0.50005 0 1 0 67.5 51 L 22.5 51 z M 70.5 51 A 0.50005 0.50005 0 1 0 70.5 52 L 73.5 52 A 0.50005 0.50005 0 1 0 73.5 51 L 70.5 51 z M 76.5 51 A 0.50005 0.50005 0 1 0 76.5 52 L 78.5 52 A 0.50005 0.50005 0 1 0 78.5 51 L 76.5 51 z M 17 67 A 1.0001 1.0001 0 0 0 16 68 L 16 78 A 1.0001 1.0001 0 0 0 17 79 L 83 79 A 1.0001 1.0001 0 0 0 84 78 L 84 68 A 1.0001 1.0001 0 0 0 83 67 L 17 67 z M 18 69 L 82 69 L 82 74 L 26.5 74 A 0.50005 0.50005 0 1 0 26.5 75 L 82 75 L 82 77 L 18 77 L 18 69 z M 21.5 74 A 0.50005 0.50005 0 1 0 21.5 75 L 23.5 75 A 0.50005 0.50005 0 1 0 23.5 74 L 21.5 74 z"/></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,4 +0,0 @@
<svg width="24" height="27" viewBox="0 0 24 27" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.5 8.95076V25.6174H23.5V8.95076L12 0.617432L0.5 8.95076Z" stroke="#000000"/>
<path d="M15.8357 25.6171V15.2004H8.16907V25.6171" stroke="#000000"/>
</svg>

Before

Width:  |  Height:  |  Size: 261 B

View File

@@ -1,4 +0,0 @@
<svg width="24" height="27" viewBox="0 0 24 27" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.5 8.95076V25.6174H23.5V8.95076L12 0.617432L0.5 8.95076Z" stroke="#FFE9C8"/>
<path d="M15.8357 25.6171V15.2004H8.16907V25.6171" stroke="#FFE9C8"/>
</svg>

Before

Width:  |  Height:  |  Size: 261 B

View File

@@ -1 +0,0 @@
<svg fill="none" height="27" viewBox="0 0 24 27" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m.5 8.95076v16.66664h23v-16.66664l-11.5-8.333328z" fill="#74000a" stroke="#ffe9c8"/><path d="m15.8357 25.6171v-10.4167h-7.66663v10.4167" fill="#74000a"/><path d="m15.8357 25.6171v-10.4167h-7.66663v10.4167" stroke="#ffe9c8"/></svg>

Before

Width:  |  Height:  |  Size: 334 B

View File

@@ -1,3 +0,0 @@
<svg width="100" height="90" viewBox="0 0 100 90" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M93.3636 15.8877H73.7455V11.2591C73.7455 5.05435 68.7 0 62.5 0H37.2909C31.0909 0 26.0455 5.04529 26.0455 11.2591V15.8877H6.63636C2.98182 15.8877 0 18.8678 0 22.5272V41.2772C0 43.4783 1.46364 45.3895 3.57273 46.0054V83.3696C3.57273 87.029 6.54545 90 10.1909 90H89.8091C93.4636 90 96.4273 87.029 96.4273 83.3696V46.0054C98.5364 45.3895 100 43.4783 100 41.2772V22.5272C100 18.8678 97.0273 15.8877 93.3636 15.8877ZM93.7 83.3696C93.7 85.5254 91.9545 87.2826 89.8091 87.2826H10.1909C8.04545 87.2826 6.3 85.5254 6.3 83.3696V46.712L43.7364 56.2138V60.933C43.7364 63.1522 45.5455 64.9547 47.7636 64.9547H52.0364C54.2545 64.9547 56.0546 63.1522 56.0546 60.933V56.2772L93.7 46.712V83.3696ZM52.0273 50.1993C52.7455 50.1993 53.3182 50.788 53.3182 51.5036V60.933C53.3182 61.6576 52.7364 62.2373 52.0273 62.2373H47.7545C47.0364 62.2373 46.4545 61.6485 46.4545 60.933V51.5036C46.4545 50.779 47.0364 50.1993 47.7545 50.1993H52.0273ZM97.2636 41.2772C97.2636 42.2917 96.5727 43.1793 95.5818 43.433C55.2455 53.6775 56.0455 53.5688 56.0455 53.4783V51.5127C56.0455 49.2935 54.2364 47.4909 52.0273 47.4909H47.7545C45.5636 47.4909 43.7273 49.2482 43.7273 51.5127V53.4149L4.40909 43.433C3.41818 43.1793 2.72727 42.3007 2.72727 41.2772V22.5272C2.72727 20.3623 4.48182 18.6051 6.63636 18.6051H93.3636C95.5182 18.6051 97.2727 20.3623 97.2727 22.5272V41.2772H97.2636ZM28.7727 11.25C28.7727 6.53986 32.5909 2.70833 37.2909 2.70833H62.5C67.2 2.70833 71.0182 6.53986 71.0182 11.25V15.8786H66.3182V11.25C66.3182 9.13949 64.6 7.41848 62.5 7.41848H37.2909C35.1818 7.41848 33.4727 9.13949 33.4727 11.25V15.8786H28.7727V11.25ZM36.2 15.8786V11.25C36.2 10.6341 36.6909 10.1359 37.2909 10.1359H62.5C63.1 10.1359 63.5909 10.6341 63.5909 11.25V15.8786H36.1909H36.2Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,3 +0,0 @@
<svg width="110" height="100" viewBox="0 0 110 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M102.7 17.54H81.12V12.43C81.12 5.58 75.57 0 68.75 0H41.02C34.2 0 28.65 5.57 28.65 12.43V17.54H7.3C3.28 17.54 0 20.83 0 24.87V45.57C0 48 1.61 50.11 3.93 50.79V92.04C3.93 96.08 7.2 99.36 11.21 99.36H98.79C102.81 99.36 106.07 96.08 106.07 92.04V50.79C108.39 50.11 110 48 110 45.57V24.87C110 20.83 106.73 17.54 102.7 17.54ZM103.07 92.04C103.07 94.42 101.15 96.36 98.79 96.36H11.21C8.85 96.36 6.93 94.42 6.93 92.04V51.57L48.11 62.06V67.27C48.11 69.72 50.1 71.71 52.54 71.71H57.24C59.68 71.71 61.66 69.72 61.66 67.27V62.13L103.07 51.57V92.04ZM57.23 55.42C58.02 55.42 58.65 56.07 58.65 56.86V67.27C58.65 68.07 58.01 68.71 57.23 68.71H52.53C51.74 68.71 51.1 68.06 51.1 67.27V56.86C51.1 56.06 51.74 55.42 52.53 55.42H57.23ZM106.99 45.57C106.99 46.69 106.23 47.67 105.14 47.95C60.77 59.26 61.65 59.14 61.65 59.04V56.87C61.65 54.42 59.66 52.43 57.23 52.43H52.53C50.12 52.43 48.1 54.37 48.1 56.87V58.97L4.85 47.95C3.76 47.67 3 46.7 3 45.57V24.87C3 22.48 4.93 20.54 7.3 20.54H102.7C105.07 20.54 107 22.48 107 24.87V45.57H106.99ZM31.65 12.42C31.65 7.22 35.85 2.99 41.02 2.99H68.75C73.92 2.99 78.12 7.22 78.12 12.42V17.53H72.95V12.42C72.95 10.09 71.06 8.19 68.75 8.19H41.02C38.7 8.19 36.82 10.09 36.82 12.42V17.53H31.65V12.42ZM39.82 17.53V12.42C39.82 11.74 40.36 11.19 41.02 11.19H68.75C69.41 11.19 69.95 11.74 69.95 12.42V17.53H39.81H39.82Z" fill="#FFE9C8"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,3 +0,0 @@
<svg width="102" height="92" viewBox="0 0 102 92" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M63.5 0.5C69.9767 0.5 75.245 5.77871 75.2451 12.2588V16.3877H94.3633C98.3036 16.3877 101.5 19.5923 101.5 23.5273V42.2773C101.5 44.5771 100.051 46.5844 97.9277 47.3652V84.3691C97.9277 88.3036 94.741 91.4997 90.8096 91.5H11.1904C7.26853 91.4997 4.07227 88.304 4.07227 84.3691V47.3652C1.94941 46.5844 0.500071 44.5771 0.5 42.2773V23.5273C0.5 19.5918 3.70596 16.3877 7.63672 16.3877H26.5459V12.2588C26.546 5.76939 31.8146 0.5 38.291 0.5H63.5ZM7.7998 84.3691C7.7998 86.2515 9.32416 87.782 11.1904 87.7822H90.8096C92.6758 87.782 94.2002 86.2515 94.2002 84.3691V48.3545L57.5547 57.665V61.9326C57.5547 64.4275 55.5309 66.4551 53.0361 66.4551H48.7637C46.2703 66.4551 44.2363 64.4289 44.2363 61.9326V57.6025L7.7998 48.3535V84.3691ZM48.7549 51.6992C48.3134 51.6992 47.9541 52.0548 47.9541 52.5039V61.9326C47.9541 62.3749 48.3157 62.7373 48.7549 62.7373H53.0273C53.4574 62.7373 53.8184 62.3839 53.8184 61.9326V52.5039C53.8184 52.0571 53.462 51.6993 53.0273 51.6992H48.7549ZM7.63672 20.1055C5.75962 20.1055 4.22754 21.6373 4.22754 23.5273V42.2773C4.22761 43.0695 4.76073 43.7505 5.5332 43.9482H5.53223L44.2275 53.7725V52.5127C44.2275 49.9652 46.2947 47.9912 48.7549 47.9912H53.0273C55.5123 47.9912 57.5459 50.0171 57.5459 52.5127V53.8721C58.1385 53.7243 59.2979 53.4278 61.5635 52.8467C66.4059 51.6045 76.2902 49.0704 96.458 43.9482L96.5996 43.9062C97.2939 43.665 97.7636 43.0127 97.7637 42.2773V41.7773H97.7725V23.5273C97.7725 21.6373 96.2404 20.1055 94.3633 20.1055H7.63672ZM38.291 4.20801C33.8686 4.20801 30.2725 7.81459 30.2725 12.25V16.3789H33.9727V12.25C33.9727 9.8655 35.9036 7.91895 38.291 7.91895H63.5C65.8775 7.91895 67.8184 9.86473 67.8184 12.25V16.3789H71.5186V12.25C71.5186 7.81459 67.9225 4.20801 63.5 4.20801H38.291ZM38.291 11.6357C37.9761 11.6357 37.7002 11.9012 37.7002 12.25V16.3789H64.0908V12.25C64.0908 11.9012 63.8149 11.6357 63.5 11.6357H38.291Z" fill="#BD2D2D" stroke="#FFE9C8"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="100" height="100">
<path d="M0 0 C33 0 66 0 100 0 C100 23.76 100 47.52 100 72 C67 72 34 72 0 72 C0 48.24 0 24.48 0 0 Z M4 4 C3.46383745 8.70053019 3.46383745 8.70053019 5.30664062 10.5546875 C5.91701172 10.99039062 6.52738281 11.42609375 7.15625 11.875 C7.84114502 12.37870117 8.52604004 12.88240234 9.23168945 13.40136719 C9.98023193 13.92891602 10.72877441 14.45646484 11.5 15 C13.06813799 16.14868129 14.63450237 17.29978719 16.19921875 18.453125 C17.40070557 19.33194336 17.40070557 19.33194336 18.62646484 20.22851562 C22.28176453 22.95664302 25.79456149 25.84835522 29.3125 28.75 C31.2591282 30.33484221 33.20813973 31.91671841 35.15722656 33.49853516 C36.36876709 34.48568066 37.57657813 35.4774244 38.78027344 36.47412109 C40.40268905 37.81286849 42.04179632 39.1275644 43.6875 40.4375 C44.59886719 41.17871094 45.51023438 41.91992188 46.44921875 42.68359375 C48.88630843 44.26660079 48.88630843 44.26660079 51.37890625 43.5859375 C54.95082046 41.42468986 58.06328957 38.87595616 61.25 36.1875 C67.05660886 31.37582668 72.93368091 26.68843648 78.9375 22.125 C80.0061731 21.30745239 80.0061731 21.30745239 81.09643555 20.47338867 C84.06177854 18.20933035 87.03509444 15.97490703 90.0703125 13.8046875 C91.30394531 12.91136719 91.30394531 12.91136719 92.5625 12 C93.24441406 11.525625 93.92632812 11.05125 94.62890625 10.5625 C96.54964019 8.72009187 96.54964019 8.72009187 96 4 C65.64 4 35.28 4 4 4 Z M4 15 C4 32.49 4 49.98 4 68 C34.36 68 64.72 68 96 68 C96 50.51 96 33.02 96 15 C91.10723979 18.66957016 86.23777639 22.33985116 81.4375 26.125 C80.5556604 26.81843506 80.5556604 26.81843506 79.65600586 27.52587891 C76.42735841 30.06945531 73.21156659 32.62826175 70.0078125 35.203125 C69.01890015 35.99759033 69.01890015 35.99759033 68.01000977 36.80810547 C66.75119369 37.82090246 65.49376977 38.83543328 64.23803711 39.85205078 C63.07629198 40.7874235 61.90867537 41.71555794 60.73486328 42.63574219 C59.54616335 43.57050931 58.37318371 44.52551784 57.21435547 45.49707031 C54.26370419 47.84496996 52.75924576 48.97890984 48.90625 49.0859375 C45.41094599 47.77989648 43.28715117 46.10681719 40.5 43.625 C39.44697905 42.70771873 38.39222174 41.79242782 37.3359375 40.87890625 C36.7903418 40.40340332 36.24474609 39.92790039 35.68261719 39.43798828 C32.89861809 37.05874355 30.01440497 34.81161154 27.125 32.5625 C26.54911133 32.11293945 25.97322266 31.66337891 25.37988281 31.20019531 C24.19857561 30.27805578 23.01693136 29.35634787 21.83496094 28.43505859 C19.90812651 26.92814897 17.98846374 25.41247563 16.0703125 23.89453125 C15.43077637 23.38913818 14.79124023 22.88374512 14.13232422 22.36303711 C12.90121746 21.38980809 11.671035 20.41540842 10.44189453 19.43969727 C7.37045638 16.99238729 7.37045638 16.99238729 4 15 Z " fill="#000000" transform="translate(0,14)"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -1,7 +0,0 @@
<svg width="118" height="108" viewBox="0 0 118 108" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M80.1955 59.9449H61.5784V107.52H80.1955V59.9449Z" fill="black"/>
<path d="M31.5063 59.9449H22.1965V107.52H31.5063V59.9449Z" fill="black"/>
<path d="M97.7112 0.0305315L97.7323 0H19.6963L19.7104 0.0305315C8.77192 0.356983 0 9.30504 0 20.3245C0 30.9295 8.12254 39.6251 18.4844 40.5563C22.3596 40.5458 31.0622 39.4924 31.4051 30.569C31.6188 24.9959 27.2599 20.2905 21.6879 20.0779L21.9063 14.3545C26.1361 14.5154 30.0476 16.3132 32.9223 19.418C35.7969 22.5216 37.2918 26.56 37.1298 30.7874C36.8068 39.1871 31.0998 44.8343 22.1987 46.0402V54.2168H95.2346V46.1436C91.7576 45.7373 88.6704 44.6558 86.1727 42.9272C82.1683 40.1618 79.9489 35.9801 79.7528 30.8332C79.5896 26.6058 81.0845 22.5686 83.9626 19.4661C86.835 16.3602 90.7477 14.5623 94.9751 14.4026L95.1947 20.1273C92.4962 20.2283 89.9997 21.3767 88.1642 23.3589C86.33 25.3411 85.3765 27.9175 85.4787 30.616C85.6043 33.9345 86.9348 36.4909 89.4313 38.2183C91.6249 39.7343 94.7203 40.5528 98.1985 40.5951C108.909 40.0232 117.429 31.1808 117.429 20.3245C117.429 9.30387 108.654 0.35346 97.7112 0.0305315Z" fill="black"/>
<path d="M95.2336 59.9449H85.9238V107.52H95.2336V59.9449Z" fill="black"/>
<path d="M55.8515 59.9449H37.2344V107.52H55.8515V59.9449Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,7 +0,0 @@
<svg width="118" height="108" viewBox="0 0 118 108" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M80.1955 59.9449H61.5784V107.52H80.1955V59.9449Z" fill="#FFE9C8"/>
<path d="M31.5063 59.9449H22.1965V107.52H31.5063V59.9449Z" fill="#FFE9C8"/>
<path d="M97.7112 0.0305315L97.7323 0H19.6963L19.7104 0.0305315C8.77192 0.356983 0 9.30504 0 20.3245C0 30.9295 8.12254 39.6251 18.4844 40.5563C22.3596 40.5458 31.0622 39.4924 31.4051 30.569C31.6188 24.9959 27.2599 20.2905 21.6879 20.0779L21.9063 14.3545C26.1361 14.5154 30.0476 16.3132 32.9223 19.418C35.7969 22.5216 37.2918 26.56 37.1298 30.7874C36.8068 39.1871 31.0998 44.8343 22.1987 46.0402V54.2168H95.2346V46.1436C91.7576 45.7373 88.6704 44.6558 86.1727 42.9272C82.1683 40.1618 79.9489 35.9801 79.7528 30.8332C79.5896 26.6058 81.0845 22.5686 83.9626 19.4661C86.835 16.3602 90.7477 14.5623 94.9751 14.4026L95.1947 20.1273C92.4962 20.2283 89.9997 21.3767 88.1642 23.3589C86.33 25.3411 85.3765 27.9175 85.4787 30.616C85.6043 33.9345 86.9348 36.4909 89.4313 38.2183C91.6249 39.7343 94.7203 40.5528 98.1985 40.5951C108.909 40.0232 117.429 31.1808 117.429 20.3245C117.429 9.30387 108.654 0.35346 97.7112 0.0305315Z" fill="#FFE9C8"/>
<path d="M95.2336 59.9449H85.9238V107.52H95.2336V59.9449Z" fill="#FFE9C8"/>
<path d="M55.8515 59.9449H37.2344V107.52H55.8515V59.9449Z" fill="#FFE9C8"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 3" viewBox="0 0 128 160" x="0px" y="0px"><path d="M111.7,31.86h-21.58v-5.11c0-6.85-5.55-12.43-12.37-12.43h-27.73c-6.82,0-12.37,5.57-12.37,12.43v5.11H16.3c-4.02,0-7.3,3.29-7.3,7.33v20.7c0,2.43,1.61,4.54,3.93,5.22v41.25c0,4.04,3.27,7.32,7.28,7.32H107.79c4.02,0,7.28-3.28,7.28-7.32v-41.25c2.32-.68,3.93-2.79,3.93-5.22v-20.7c0-4.04-3.27-7.33-7.3-7.33Zm.37,74.5c0,2.38-1.92,4.32-4.28,4.32H20.21c-2.36,0-4.28-1.94-4.28-4.32v-40.47l41.18,10.49v5.21c0,2.45,1.99,4.44,4.43,4.44h4.7c2.44,0,4.42-1.99,4.42-4.44v-5.14l41.41-10.56v40.47Zm-45.84-36.62c.79,0,1.42,.65,1.42,1.44v10.41c0,.8-.64,1.44-1.42,1.44h-4.7c-.79,0-1.43-.65-1.43-1.44v-10.41c0-.8,.64-1.44,1.43-1.44h4.7Zm49.76-9.85c0,1.12-.76,2.1-1.85,2.38-44.37,11.31-43.49,11.19-43.49,11.09v-2.17c0-2.45-1.99-4.44-4.42-4.44h-4.7c-2.41,0-4.43,1.94-4.43,4.44v2.1L13.85,62.27c-1.09-.28-1.85-1.25-1.85-2.38v-20.7c0-2.39,1.93-4.33,4.3-4.33H111.7c2.37,0,4.3,1.94,4.3,4.33v20.7ZM40.65,26.74c0-5.2,4.2-9.43,9.37-9.43h27.73c5.17,0,9.37,4.23,9.37,9.43v5.11h-5.17v-5.11c0-2.33-1.89-4.23-4.2-4.23h-27.73c-2.32,0-4.2,1.9-4.2,4.23v5.11h-5.17v-5.11Zm8.17,5.11v-5.11c0-.68,.54-1.23,1.2-1.23h27.73c.66,0,1.2,.55,1.2,1.23v5.11h-30.14Z"/><text x="0" y="143" fill="#000000" font-size="5px" font-weight="bold" font-family="'Helvetica Neue', Helvetica, Arial-Unicode, Arial, Sans-serif">Created by nasril</text><text x="0" y="148" fill="#000000" font-size="5px" font-weight="bold" font-family="'Helvetica Neue', Helvetica, Arial-Unicode, Arial, Sans-serif">from the Noun Project</text></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1,3 +0,0 @@
<svg width="34" height="32" viewBox="0 0 34 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M22.4912 0.5C24.6609 0.500107 26.4463 2.29218 26.4463 4.50195C26.4461 5.9638 25.6634 7.24788 24.502 7.94824L23.6514 8.46094L24.5693 8.83887C26.587 9.66866 28.0146 11.6745 28.0146 14.0195V14.5029L28.4541 14.5566C30.4025 14.7942 31.9307 16.4869 31.9307 18.5342C31.9306 19.9965 31.1509 21.2779 29.9912 21.9766L29.1406 22.4893L30.0596 22.8672C32.0762 23.6969 33.5 25.7015 33.5 28.0469V31.4609C33.4998 31.4881 33.4804 31.4983 33.4697 31.499C33.466 31.4988 33.4624 31.4985 33.459 31.4971C33.4553 31.4955 33.4524 31.4944 33.4512 31.4932L33.4482 31.4902L33.4365 31.458V28.0469C33.4365 24.9911 31.019 22.5352 27.9805 22.5352C24.9421 22.5352 22.5225 24.9924 22.5225 28.0469V31.4629C22.5225 31.4743 22.5176 31.4844 22.5117 31.4902C22.5051 31.4967 22.4976 31.4988 22.4902 31.499C22.485 31.4985 22.4784 31.4966 22.4727 31.4912L22.4609 31.4609V28.0469C22.4609 24.9905 20.0379 22.5352 17 22.5352C13.9614 22.5352 11.544 24.9925 11.5439 28.0469V31.4609C11.5439 31.4744 11.5382 31.4841 11.5312 31.4912C11.5246 31.498 11.5191 31.5 11.5137 31.5C11.5104 31.5 11.508 31.4997 11.5049 31.499C11.4948 31.4967 11.4805 31.4846 11.4805 31.4629V28.0488C11.4805 24.9931 9.0629 22.5373 6.02441 22.5371C2.98626 22.5371 0.563477 24.9939 0.563477 28.0488V31.4609C0.563297 31.4882 0.542917 31.4999 0.530273 31.5C0.524251 31.5 0.518186 31.4977 0.511719 31.4912C0.505432 31.4847 0.501504 31.4756 0.500977 31.4629V28.0488C0.500977 25.7039 1.92786 23.7001 3.94531 22.8701L4.86426 22.4912L4.0127 21.9795C2.85121 21.2805 2.06934 19.997 2.06934 18.5352C2.06949 16.4873 3.60107 14.7963 5.55176 14.5586L5.99121 14.5049V14.0205C5.99124 11.6755 7.41775 9.67071 9.43652 8.84082L10.3555 8.46289L9.50391 7.9502C8.34227 7.24961 7.55957 5.96483 7.55957 4.50293C7.55962 2.29286 9.34267 0.502076 11.5137 0.501953H11.5977C13.73 0.546093 15.4668 2.31921 15.4668 4.50195C15.4666 5.96451 14.6864 7.24824 13.5254 7.94824L12.6758 8.46094L13.5938 8.83887C14.9033 9.37789 15.9663 10.4144 16.5479 11.7168L17.0039 12.7393L17.4609 11.7168C18.0426 10.4142 19.1043 9.3778 20.415 8.83887L21.334 8.46094L20.4834 7.94824C19.322 7.24792 18.5402 5.96407 18.54 4.50195C18.54 2.29132 20.3205 0.5 22.4912 0.5ZM11.5127 8.50879C8.47454 8.50879 6.05176 10.9655 6.05176 14.0205V14.5039L6.49219 14.5566C8.44316 14.7921 9.97363 16.4858 9.97363 18.5342C9.9735 19.9963 9.19367 21.2769 8.03418 21.9756L7.18359 22.4883L8.10156 22.8662C9.41094 23.4051 10.4731 24.4415 11.0547 25.7441L11.1865 26.04H11.8369L11.9688 25.7441C12.552 24.4411 13.6128 23.405 14.9219 22.8662L15.8398 22.4883L14.9893 21.9756C13.8297 21.2769 13.0499 19.9963 13.0498 18.5342C13.0498 16.4857 14.5807 14.793 16.5322 14.5566L16.9717 14.5029V14.0205C16.9717 10.9645 14.5521 8.50879 11.5137 8.50879H11.5127ZM22.4902 8.50781C19.4517 8.50781 17.0344 10.9643 17.0342 14.0186V14.5029L17.4736 14.5566C19.4239 14.7945 20.9541 16.4876 20.9541 18.5342C20.954 19.9961 20.173 21.2768 19.0117 21.9756L18.1602 22.4883L19.0791 22.8662C20.3897 23.4051 21.452 24.4414 22.0352 25.7441L22.168 26.04H22.8174L22.9492 25.7441C23.5309 24.4415 24.5929 23.4051 25.9023 22.8662L26.8213 22.4883L25.9697 21.9756C24.8102 21.2769 24.0304 19.9962 24.0303 18.5342C24.0303 16.4856 25.5595 14.793 27.5107 14.5566L27.9512 14.5029V14.0205C27.9512 11.1335 25.7892 8.78398 22.9893 8.53223V8.50781H22.4902ZM6.02344 14.6074C3.8627 14.6074 2.13208 16.3662 2.13184 18.5332C2.13184 20.7012 3.86338 22.4561 6.02344 22.4561C8.18395 22.4559 9.91211 20.7006 9.91211 18.5332C9.91187 16.3669 8.18463 14.6075 6.02344 14.6074ZM16.999 14.6074C14.8379 14.6076 13.1106 16.3669 13.1104 18.5332C13.1104 20.7005 14.8386 22.4559 16.999 22.4561C19.1591 22.4561 20.8916 20.7012 20.8916 18.5332C20.8914 16.3662 19.1598 14.6074 16.999 14.6074ZM27.9795 14.6074C25.8182 14.6075 24.0911 16.3668 24.0908 18.5332C24.0908 20.7006 25.8189 22.456 27.9795 22.4561C30.1404 22.4561 31.8672 20.7004 31.8672 18.5332C31.8669 16.3671 30.1411 14.6074 27.9795 14.6074ZM11.5137 0.579102C9.35372 0.579223 7.62207 2.33401 7.62207 4.50195C7.62232 6.66883 9.35304 8.42761 11.5137 8.42773C13.675 8.42773 15.4031 6.66835 15.4033 4.50195C15.4033 2.3345 13.6743 0.579102 11.5137 0.579102ZM22.4902 0.579102C20.3293 0.579102 18.6025 2.33478 18.6025 4.50195C18.6028 6.66807 20.3287 8.42773 22.4902 8.42773C24.6506 8.42762 26.3835 6.66912 26.3838 4.50195C26.3838 2.33373 24.6499 0.579213 22.4902 0.579102Z" fill="black" stroke="#000000"/>
</svg>

Before

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -1,3 +0,0 @@
<svg width="27" height="25" viewBox="0 0 27 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.14339 0.00116273C7.19618 0.00116273 5.60647 1.57928 5.60647 3.51799C5.60647 4.80237 6.30553 5.93008 7.34256 6.5453C5.59377 7.25256 4.36053 8.95969 4.36053 10.9536V10.9858C2.61174 11.1955 1.24591 12.6837 1.24591 14.4808C1.24591 15.7652 1.94497 16.8918 2.982 17.5058C1.23436 18.213 0.00115341 19.919 0.00115341 21.9129V24.5807H0C0.00115348 24.8134 0.190335 25.0011 0.423355 25C0.65522 24.9988 0.843255 24.8122 0.844407 24.5807V21.9129C0.844407 19.7381 2.59435 17.9977 4.78383 17.9977C6.97331 17.9977 8.71971 19.737 8.71971 21.9129V24.5807C8.71971 24.7777 8.85698 24.947 9.04848 24.9896C9.07962 24.9965 9.11077 25 9.14307 25C9.37493 25 9.56297 24.8122 9.56412 24.5807V21.9117C9.56412 19.7369 11.3106 17.9965 13.5 17.9965C15.6894 17.9965 17.4394 19.7359 17.4394 21.9117V24.5807C17.4406 24.8122 17.6274 24.9988 17.8593 25C17.9712 25 18.0785 24.9562 18.1581 24.8779C18.2377 24.7996 18.2827 24.6924 18.2827 24.5807V21.9117C18.2827 19.7369 20.0303 17.9965 22.2197 17.9965C24.4092 17.9965 26.1556 19.7359 26.1556 21.9117V24.5807C26.1568 24.6924 26.2017 24.7996 26.2813 24.8779C26.3598 24.9562 26.4682 25 26.5801 25C26.8108 24.9988 26.9988 24.8122 27 24.5807V21.9117C27 19.9178 25.7692 18.2106 24.0215 17.5034C25.0574 16.8895 25.7542 15.7641 25.7542 14.4797C25.7542 12.6839 24.3918 11.1943 22.6443 10.9847V10.9524C22.6443 8.95847 21.4099 7.25128 19.6622 6.54414C20.6993 5.92903 21.3983 4.8013 21.3983 3.51683C21.3983 1.57818 19.8064 0 17.8605 0C15.9133 0 14.326 1.57812 14.326 3.51683C14.326 4.80121 15.0239 5.92892 16.0609 6.54414C14.9246 7.00375 14.0064 7.88611 13.5035 8.99424C13.0005 7.88611 12.0811 7.00375 10.946 6.54414C11.9831 5.92903 12.6798 4.8013 12.6798 3.51683C12.6798 1.57818 11.0914 0 9.14527 0L9.14339 0.00116273ZM9.14339 0.843213C10.6361 0.843213 11.8346 2.03544 11.8346 3.51678C11.8346 4.99812 10.6361 6.1938 9.14339 6.1938C7.65069 6.1938 6.44985 4.99812 6.44985 3.51678C6.44985 2.03544 7.65069 0.843213 9.14339 0.843213ZM17.8597 0.843213C19.3524 0.843213 20.5544 2.03544 20.5544 3.51678C20.5544 4.99812 19.3524 6.1938 17.8597 6.1938C16.367 6.1938 15.1696 4.99812 15.1696 3.51678C15.1696 2.03544 16.367 0.843213 17.8597 0.843213ZM9.14339 7.03821C11.3328 7.03821 13.0804 8.77757 13.0804 10.9534V10.9845C11.3305 11.193 9.96582 12.6824 9.96582 14.4795C9.96582 15.7639 10.6626 16.8893 11.6985 17.5033C10.5634 17.9629 9.6463 18.8453 9.14221 19.9534H9.14105C8.63811 18.8453 7.71988 17.9629 6.5848 17.5033C7.62069 16.8894 8.31744 15.7639 8.31744 14.4795C8.31744 12.6825 6.95278 11.1921 5.20281 10.9845V10.9534C5.20281 8.77863 6.95275 7.03821 9.14223 7.03821H9.14339ZM17.8597 7.03821C20.0492 7.03821 21.7991 8.77757 21.7991 10.9534V10.9845C20.0492 11.193 18.6857 12.6824 18.6857 14.4795C18.6857 15.7639 19.3825 16.8893 20.4183 17.5033C19.2832 17.9629 18.365 18.8453 17.8621 19.9534H17.8609C17.3568 18.8453 16.4386 17.9629 15.3024 17.5033C16.3394 16.8894 17.0373 15.7639 17.0373 14.4795C17.0373 12.6837 15.6726 11.1942 13.9238 10.9845V10.9523C13.9238 8.77748 15.6703 7.03705 17.8597 7.03705L17.8597 7.03821ZM4.78315 11.8024C6.27585 11.8024 7.47439 12.9981 7.47439 14.4794C7.47439 15.9608 6.27585 17.153 4.78315 17.153C3.29045 17.153 2.08961 15.9608 2.08961 14.4794C2.08961 12.9981 3.29045 11.8024 4.78315 11.8024ZM13.4995 11.8024C14.9922 11.8024 16.193 12.9981 16.193 14.4794C16.193 15.9608 14.9922 17.153 13.4995 17.153C12.0068 17.153 10.8083 15.9608 10.8083 14.4794C10.8083 12.9981 12.0068 11.8024 13.4995 11.8024ZM22.2191 11.8024C23.7118 11.8024 24.9092 12.9981 24.9092 14.4794C24.9092 15.9608 23.7118 17.153 22.2191 17.153C20.7264 17.153 19.5278 15.9608 19.5278 14.4794C19.5278 12.9981 20.7264 11.8024 22.2191 11.8024Z" fill="#FFE9C8"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

@@ -1,13 +0,0 @@
<svg width="27" height="25" viewBox="0 0 27 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<ellipse cx="9" cy="3.5" rx="3" ry="3.5" fill="#74000A"/>
<ellipse cx="18" cy="3.3" rx="3" ry="3.3" fill="#74000A"/>
<circle cx="13.5" cy="14.5" r="3.5" fill="#74000A"/>
<circle cx="5.5" cy="14.5" r="3.5" fill="#74000A"/>
<circle cx="21.5" cy="14.5" r="3.5" fill="#74000A"/>
<ellipse cx="9.25" cy="11" rx="4.25" ry="4" fill="#74000A"/>
<ellipse cx="17.75" cy="11.5" rx="4.75" ry="4.5" fill="#74000A"/>
<ellipse cx="13.5" cy="19" rx="7" ry="6" fill="#74000A"/>
<ellipse cx="13.5" cy="20.5" rx="12.5" ry="4.5" fill="#74000A"/>
<rect x="0.5" y="20" width="26" height="5" fill="#74000A"/>
<path d="M9.14339 0.00116273C7.19618 0.00116273 5.60647 1.57928 5.60647 3.51799C5.60647 4.80237 6.30553 5.93008 7.34256 6.5453C5.59377 7.25256 4.36053 8.95969 4.36053 10.9536V10.9858C2.61174 11.1955 1.24591 12.6837 1.24591 14.4808C1.24591 15.7652 1.94497 16.8918 2.982 17.5058C1.23436 18.213 0.00115341 19.919 0.00115341 21.9129V24.5807H0C0.00115348 24.8134 0.190335 25.0011 0.423355 25C0.65522 24.9988 0.843255 24.8122 0.844407 24.5807V21.9129C0.844407 19.7381 2.59435 17.9977 4.78383 17.9977C6.97331 17.9977 8.71971 19.737 8.71971 21.9129V24.5807C8.71971 24.7777 8.85698 24.947 9.04848 24.9896C9.07962 24.9965 9.11077 25 9.14307 25C9.37493 25 9.56297 24.8122 9.56412 24.5807V21.9117C9.56412 19.7369 11.3106 17.9965 13.5 17.9965C15.6894 17.9965 17.4394 19.7359 17.4394 21.9117V24.5807C17.4406 24.8122 17.6274 24.9988 17.8593 25C17.9712 25 18.0785 24.9562 18.1581 24.8779C18.2377 24.7996 18.2827 24.6924 18.2827 24.5807V21.9117C18.2827 19.7369 20.0303 17.9965 22.2197 17.9965C24.4092 17.9965 26.1556 19.7359 26.1556 21.9117V24.5807C26.1568 24.6924 26.2017 24.7996 26.2813 24.8779C26.3598 24.9562 26.4682 25 26.5801 25C26.8108 24.9988 26.9988 24.8122 27 24.5807V21.9117C27 19.9178 25.7692 18.2106 24.0215 17.5034C25.0574 16.8895 25.7542 15.7641 25.7542 14.4797C25.7542 12.6839 24.3918 11.1943 22.6443 10.9847V10.9524C22.6443 8.95847 21.4099 7.25128 19.6622 6.54414C20.6993 5.92903 21.3983 4.8013 21.3983 3.51683C21.3983 1.57818 19.8064 0 17.8605 0C15.9133 0 14.326 1.57812 14.326 3.51683C14.326 4.80121 15.0239 5.92892 16.0609 6.54414C14.9246 7.00375 14.0064 7.88611 13.5035 8.99424C13.0005 7.88611 12.0811 7.00375 10.946 6.54414C11.9831 5.92903 12.6798 4.8013 12.6798 3.51683C12.6798 1.57818 11.0914 0 9.14527 0L9.14339 0.00116273ZM9.14339 0.843213C10.6361 0.843213 11.8346 2.03544 11.8346 3.51678C11.8346 4.99812 10.6361 6.1938 9.14339 6.1938C7.65069 6.1938 6.44985 4.99812 6.44985 3.51678C6.44985 2.03544 7.65069 0.843213 9.14339 0.843213ZM17.8597 0.843213C19.3524 0.843213 20.5544 2.03544 20.5544 3.51678C20.5544 4.99812 19.3524 6.1938 17.8597 6.1938C16.367 6.1938 15.1696 4.99812 15.1696 3.51678C15.1696 2.03544 16.367 0.843213 17.8597 0.843213ZM9.14339 7.03821C11.3328 7.03821 13.0804 8.77757 13.0804 10.9534V10.9845C11.3305 11.193 9.96582 12.6824 9.96582 14.4795C9.96582 15.7639 10.6626 16.8893 11.6985 17.5033C10.5634 17.9629 9.6463 18.8453 9.14221 19.9534H9.14105C8.63811 18.8453 7.71988 17.9629 6.5848 17.5033C7.62069 16.8894 8.31744 15.7639 8.31744 14.4795C8.31744 12.6825 6.95278 11.1921 5.20281 10.9845V10.9534C5.20281 8.77863 6.95275 7.03821 9.14223 7.03821H9.14339ZM17.8597 7.03821C20.0492 7.03821 21.7991 8.77757 21.7991 10.9534V10.9845C20.0492 11.193 18.6857 12.6824 18.6857 14.4795C18.6857 15.7639 19.3825 16.8893 20.4183 17.5033C19.2832 17.9629 18.365 18.8453 17.8621 19.9534H17.8609C17.3568 18.8453 16.4386 17.9629 15.3024 17.5033C16.3394 16.8894 17.0373 15.7639 17.0373 14.4795C17.0373 12.6837 15.6726 11.1942 13.9238 10.9845V10.9523C13.9238 8.77748 15.6703 7.03705 17.8597 7.03705L17.8597 7.03821ZM4.78315 11.8024C6.27585 11.8024 7.47439 12.9981 7.47439 14.4794C7.47439 15.9608 6.27585 17.153 4.78315 17.153C3.29045 17.153 2.08961 15.9608 2.08961 14.4794C2.08961 12.9981 3.29045 11.8024 4.78315 11.8024ZM13.4995 11.8024C14.9922 11.8024 16.193 12.9981 16.193 14.4794C16.193 15.9608 14.9922 17.153 13.4995 17.153C12.0068 17.153 10.8083 15.9608 10.8083 14.4794C10.8083 12.9981 12.0068 11.8024 13.4995 11.8024ZM22.2191 11.8024C23.7118 11.8024 24.9092 12.9981 24.9092 14.4794C24.9092 15.9608 23.7118 17.153 22.2191 17.153C20.7264 17.153 19.5278 15.9608 19.5278 14.4794C19.5278 12.9981 20.7264 11.8024 22.2191 11.8024Z" fill="#FFE9C8"/>
</svg>

Before

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 64 80" x="0px" y="0px"><path d="M32,8c-10.504,0-19.05,8.546-19.05,19.05,0,13.12,17.024,27.849,17.749,28.469,.374,.321,.838,.481,1.301,.481s.927-.16,1.301-.481c.725-.621,17.749-15.35,17.749-28.469,0-10.504-8.546-19.05-19.05-19.05Zm0,27c-4.687,0-8.5-3.813-8.5-8.5s3.813-8.5,8.5-8.5,8.5,3.813,8.5,8.5-3.813,8.5-8.5,8.5Z"/></svg>

Before

Width:  |  Height:  |  Size: 398 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 64 80" x="0px" y="0px"><path d="M32,8c-10.504,0-19.05,8.546-19.05,19.05,0,13.12,17.024,27.849,17.749,28.469,.374,.321,.838,.481,1.301,.481s.927-.16,1.301-.481c.725-.621,17.749-15.35,17.749-28.469,0-10.504-8.546-19.05-19.05-19.05Zm0,27c-4.687,0-8.5-3.813-8.5-8.5s3.813-8.5,8.5-8.5,8.5,3.813,8.5,8.5-3.813,8.5-8.5,8.5Z" fill="#FFE9C8"/></svg>

Before

Width:  |  Height:  |  Size: 413 B

View File

@@ -1,71 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 511.697 511.697" xml:space="preserve">
<g transform="translate(0 1)">
<g>
<path style="fill:#FFE100;" d="M505.189,119.472L505.189,119.472c-7.81-7.81-13.885-9.546-21.695-1.736l-45.125,45.993
c-6.075,6.075-14.753,6.075-20.827,0.868l-63.349-59.01c-4.339-4.339-10.414-6.942-16.488-6.942h-94.59l-79.837,75.498
c-7.81,7.81-9.546,21.695-1.736,30.373c8.678,9.546,22.563,8.678,31.241,0l59.01-62.481h43.39L147.656,306.916H62.612
c-13.885,0-26.902,10.414-27.769,24.298c-0.868,15.62,11.281,27.77,26.034,27.77H165.88c10.414,0,19.959-4.339,27.77-12.149
l57.275-61.614l61.614,65.085L296.05,456.177c-2.603,12.149,2.603,25.166,13.885,30.373c15.62,6.942,32.108-1.736,36.447-17.356
l25.166-135.376c0.868-6.075-0.868-11.281-5.207-15.62l-71.159-72.027l69.424-69.424l45.993,45.993
c7.81,7.81,21.695,7.81,29.505,0l19.959-19.959l45.125-52.068C513.867,142.035,513.867,128.15,505.189,119.472"/>
<path style="fill:#FFE100;" d="M462.667,118.605l-0.868-0.868c-7.81-7.81-1.736-7.81-10.414,0l-34.712,45.993
c-6.075,6.075-14.753,6.075-20.827,0.868l-73.763-59.01c-4.339-4.339-4.339-6.942-10.414-6.942h-68.556l-79.837,75.498
c-7.81,7.81-9.546,21.695-1.736,30.373c8.678,9.546,4.339,8.678,12.149,0l60.746-62.481h34.712L121.623,306.916h-59.01
c-13.885,0-26.902,10.414-27.769,24.298c-0.868,15.62,11.281,27.77,26.034,27.77h95.458l69.424-72.895l60.746,64.217
l-16.488,105.871c-2.603,12.149,2.603,25.166,13.885,30.373c15.62,6.942,16.488-1.736,19.959-17.356l20.827-144.922
l-55.539-78.102l63.349-69.424l40.786,45.993c7.81,7.81,18.224-3.471,26.034-11.281l8.678-8.678l54.671-54.671
C470.477,140.299,470.477,126.415,462.667,118.605"/>
</g>
<g>
<path style="fill:#FFA800;" d="M323.819,324.272l-20.827,144.922c-2.603,11.281-3.471,19.092-10.414,19.959
c12.149,0.868,23.431-7.81,26.034-19.959l27.77-144.922l-77.234-77.234L323.819,324.272z"/>
<path style="fill:#FFA800;" d="M487.833,118.605l-0.868-0.868c-7.81-7.81-19.092-7.81-27.77-1.736
c0.868,0.868,0.868,0.868,1.736,1.736l0.868,0.868c7.81,7.81,7.81,20.827,0,29.505l-54.671,54.671l-8.678,8.678
c-4.339,4.339-8.678,9.546-13.885,12.149c7.81,6.942,20.827,6.942,28.637-0.868l19.959-19.959l54.671-54.671
C495.643,140.299,495.643,127.282,487.833,118.605"/>
</g>
<g>
<path style="fill:#FFFFFF;" d="M163.277,207.12c-0.868-0.868-1.736-1.736-2.603-2.603c-7.81-8.678-6.942-21.695,1.736-30.373
l80.705-75.498H217.08l-79.837,75.498c-7.81,7.81-9.546,21.695-1.736,30.373S155.467,213.194,163.277,207.12"/>
<path style="fill:#FFFFFF;" d="M34.843,331.215c0.868-13.885,13.017-24.298,26.902-24.298H35.711
c-13.885,0-26.902,10.414-27.769,24.298c0,15.62,12.149,27.77,26.902,27.77h26.034C46.124,358.984,33.975,346.835,34.843,331.215"
/>
</g>
<path style="fill:#FFE100;" d="M425.351,63.933c0-24.298-19.092-43.39-43.39-43.39c-0.868,0-26.034,19.092-26.034,43.39
c0,0.868,1.736,43.39,26.034,43.39C406.26,107.323,425.351,88.232,425.351,63.933"/>
<g>
<path style="fill:#FFA800;" d="M399.318,20.543c-2.603,0-6.075,0-8.678,0.868c19.959,4.339,34.712,21.695,34.712,42.522
s-14.753,38.183-34.712,42.522c2.603,0.868,6.075,0.868,8.678,0.868c24.298,0,43.39-19.092,43.39-43.39
S423.616,20.543,399.318,20.543"/>
<path style="fill:#FFA800;" d="M356.795,71.743c0,0.868,0,0.868,0,1.736C356.795,72.611,356.795,71.743,356.795,71.743"/>
</g>
<path d="M295.182,497.832c-5.207,0-9.546-0.868-14.753-3.471c-14.753-6.942-23.431-23.431-19.092-40.786l15.62-100.664
l-52.068-54.671l-62.481,66.82c-1.736,1.736-3.471,2.603-6.075,2.603H34.843c-9.546,0-18.224-4.339-25.166-10.414
c-6.942-6.942-10.414-16.488-9.546-26.034c0.868-18.224,16.488-32.976,36.447-32.976h81.573l32.108-35.58
c3.471-3.471,8.678-3.471,12.149-0.868c3.471,3.471,3.471,8.678,0.868,12.149l-34.712,39.051c-2.603,1.736-4.339,2.603-6.942,2.603
H36.579c-10.414,0-19.092,6.942-19.092,16.488c0,5.207,1.736,9.546,4.339,13.017c3.471,3.471,7.81,5.207,13.017,5.207h118.02
l65.953-70.292c1.736-1.736,4.339-2.603,6.075-2.603c2.603,0,4.339,0.868,6.075,2.603l61.614,64.217
c1.736,1.736,2.603,4.339,2.603,6.942l-16.488,105.871c-1.736,9.546,1.736,18.224,9.546,21.695c5.207,2.603,10.414,1.736,14.753,0
c4.339-2.603,7.81-6.942,9.546-11.281l26.034-139.715l-74.63-74.631c-2.603-2.603-3.471-4.339-3.471-6.942
c0-2.603,0.868-4.339,2.603-6.075l69.424-69.424c3.471-3.471,8.678-3.471,12.149,0l45.993,45.993
c4.339,4.339,12.149,4.339,17.356,0l74.63-74.631c4.339-4.339,4.339-12.149,0-16.488l-0.868-0.868
c-5.207-5.207-13.017-5.207-17.356,0l-45.125,45.993c-8.678,8.678-23.431,9.546-32.976,0.868l-63.349-59.01
c-2.603-2.603-6.942-4.339-10.414-4.339h-91.986l-77.234,73.763c-5.207,5.207-5.207,13.017-0.868,18.224
c2.603,2.603,6.075,4.339,9.546,4.339l0,0c3.471,0,6.942-1.736,8.678-4.339l59.01-62.481c1.736-1.736,4.339-2.603,6.075-2.603
h43.39c3.471,0,6.942,1.736,7.81,5.207s0.868,6.942-1.736,9.546l-69.424,78.102c-3.471,3.471-8.678,4.339-12.149,0.868
c-3.471-3.471-3.471-8.678-0.868-12.149l56.407-63.349h-19.959l-56.407,59.878c-5.207,6.075-13.017,9.546-21.695,9.546l0,0
c-8.678,0-16.488-3.471-21.695-9.546c-10.414-11.281-9.546-30.373,1.736-42.522l79.837-76.366c1.736-3.471,3.471-4.339,6.075-4.339
h94.59c8.678,0,16.488,3.471,22.563,8.678l63.349,59.01c2.603,2.603,6.075,2.603,8.678,0l45.125-45.993
c11.281-11.281,30.373-11.281,42.522,0l0.868,0.868c11.281,11.281,11.281,30.373,0,41.654l-74.63,74.631
c-11.281,11.281-30.373,11.281-41.654,0l-39.919-39.919l-57.275,57.275l72.027,72.027c1.736,1.736,2.603,5.207,2.603,7.81
L329.026,470.93c-2.603,10.414-9.546,19.092-18.224,23.431C305.595,496.964,300.389,497.832,295.182,497.832z"/>
<path d="M187.575,241.832c0-5.207-3.471-8.678-8.678-8.678s-8.678,3.471-8.678,8.678s3.471,8.678,8.678,8.678
S187.575,247.038,187.575,241.832"/>
<path d="M399.318,116.001c-28.637,0-52.068-23.431-52.068-52.068s23.431-52.068,52.068-52.068
c28.637,0,52.068,23.431,52.068,52.068S427.955,116.001,399.318,116.001z M399.318,29.221c-19.092,0-34.712,15.62-34.712,34.712
s15.62,34.712,34.712,34.712c19.092,0,34.712-15.62,34.712-34.712S418.409,29.221,399.318,29.221z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.2 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.1 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.1 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.2 KiB

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-5.0 -10.0 110.0 135.0">
<path d="m50 96.016c-25.414 0-46.012-20.602-46.012-46.016s20.598-46.016 46.012-46.016 46.012 20.602 46.012 46.016-20.605 46.016-46.012 46.016zm-4.043-73.004v26.988c0 1.4961 0.80859 2.8008 2.0195 3.5l17.438 10.078c1.9414 1.1211 4.418 0.46094 5.543-1.4766 1.1133-1.9336 0.46094-4.4141-1.4805-5.5352l-15.43-8.9102v-24.645c0-2.2344-1.8125-4.0469-4.043-4.0469-2.2305 0-4.043 1.8125-4.043 4.0469zm30.84 0.19141c-14.801-14.801-38.793-14.801-53.59 0-14.801 14.797-14.801 38.793 0 53.594 14.797 14.801 38.793 14.801 53.59 0s14.797-38.793 0-53.594z" fill-rule="evenodd"/>
</svg>

Before

Width:  |  Height:  |  Size: 657 B

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-5.0 -10.0 110.0 135.0">
<path d="m50 96.016c-25.414 0-46.012-20.602-46.012-46.016s20.598-46.016 46.012-46.016 46.012 20.602 46.012 46.016-20.605 46.016-46.012 46.016zm-4.043-73.004v26.988c0 1.4961 0.80859 2.8008 2.0195 3.5l17.438 10.078c1.9414 1.1211 4.418 0.46094 5.543-1.4766 1.1133-1.9336 0.46094-4.4141-1.4805-5.5352l-15.43-8.9102v-24.645c0-2.2344-1.8125-4.0469-4.043-4.0469-2.2305 0-4.043 1.8125-4.043 4.0469zm30.84 0.19141c-14.801-14.801-38.793-14.801-53.59 0-14.801 14.797-14.801 38.793 0 53.594 14.797 14.801 38.793 14.801 53.59 0s14.797-38.793 0-53.594z" fill="#FFE9C8"/>
</svg>

Before

Width:  |  Height:  |  Size: 652 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48px" height="48px"><path d="M 20.5 4 A 1.50015 1.50015 0 0 0 19.066406 6 L 14.640625 6 C 12.803372 6 11.082924 6.9194511 10.064453 8.4492188 L 7.6972656 12 L 7.5 12 A 1.50015 1.50015 0 1 0 7.5 15 L 8.2636719 15 A 1.50015 1.50015 0 0 0 8.6523438 15.007812 L 11.125 38.085938 C 11.423352 40.868277 13.795836 43 16.59375 43 L 31.404297 43 C 34.202211 43 36.574695 40.868277 36.873047 38.085938 L 39.347656 15.007812 A 1.50015 1.50015 0 0 0 39.728516 15 L 40.5 15 A 1.50015 1.50015 0 1 0 40.5 12 L 40.302734 12 L 37.935547 8.4492188 C 36.916254 6.9202798 35.196001 6 33.359375 6 L 28.933594 6 A 1.50015 1.50015 0 0 0 27.5 4 L 20.5 4 z M 14.640625 9 L 33.359375 9 C 34.196749 9 34.974746 9.4162203 35.439453 10.113281 L 36.697266 12 L 11.302734 12 L 12.560547 10.113281 A 1.50015 1.50015 0 0 0 12.5625 10.111328 C 13.025982 9.4151428 13.801878 9 14.640625 9 z M 11.669922 15 L 36.330078 15 L 33.890625 37.765625 C 33.752977 39.049286 32.694383 40 31.404297 40 L 16.59375 40 C 15.303664 40 14.247023 39.049286 14.109375 37.765625 L 11.669922 15 z"/></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,30 +0,0 @@
import { Preferences } from '@capacitor/preferences';
const env = import.meta.env
export default class util {
static HOST = env.VITE_API_URL
static async authFetch(url, options = {}) {
const { value: token } = await Preferences.get({ key: 'auth_token' });
return fetch(url, {
...options,
headers: {
...options.headers,
'Authorization': `Bearer ${token}`,
'X-Client': 'mobile'
}
});
}
static async removeAuthToken() {
await Preferences.remove({ key: 'auth_token'})
}
static cssVariable(value) {
return getComputedStyle(document.documentElement)
.getPropertyValue("--" + value)
.trim();
}
}