diff --git a/.gitignore b/.gitignore
index 42a517f..991a625 100644
--- a/.gitignore
+++ b/.gitignore
@@ -149,4 +149,7 @@ dist
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
-.pnp.*
\ No newline at end of file
+.pnp.*
+
+# Config files
+config.ts
\ No newline at end of file
diff --git a/README.md b/README.md
index d9eb2ea..45276cb 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,9 @@ a frontend dashboard with stats for your ATProto PDS.
### installing
-clone the repo, install dependencies using deno:
+clone the repo, copy `config.ts.example` to `config.ts` and edit it to your liking.
+
+then, install dependencies using deno:
```sh
deno install
diff --git a/config.ts b/config.ts
deleted file mode 100644
index 8d09cf6..0000000
--- a/config.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * Configuration module for the PDS Dashboard
- */
-export class Config {
- /**
- * The base URL of the PDS (Personal Data Server)
- * @default "https://pds.witchcraft.systems"
- */
- static readonly PDS_URL: string = "https://pds.witchcraft.systems";
-
- /**
- * The base URL of the frontend service for linking to replies/quotes/accounts etc.
- * @default "https://deer.social"
- */
- static readonly FRONTEND_URL: string = "https://deer.social";
-
- /**
- * Maximum number of posts to fetch from the PDS per request
- * Should be around 20 for about 10 users on the pds
- * The more users you have, the lower the number should be
- * since sorting is slow and is done on the frontend
- * @default 20
- */
- static readonly MAX_POSTS: number = 20;
-
- /**
- * Footer text for the dashboard, you probably want to change this
- */
- static readonly FOOTER_TEXT: string =
- "Astrally projected from witchcraft.systems
Source (github mirror)";
-
- /**
- * Whether to show the posts that are in the future
- * @default false
- */
- static readonly SHOW_FUTURE_POSTS: boolean = false;
-}
diff --git a/config.ts.example b/config.ts.example
new file mode 100644
index 0000000..3b78dde
--- /dev/null
+++ b/config.ts.example
@@ -0,0 +1,44 @@
+/**
+ * Configuration module for the PDS Dashboard
+ */
+export class Config {
+ /**
+ * The base URL of the PDS (Personal Data Server).
+ * @default none
+ */
+ static readonly PDS_URL: string = "";
+
+ /**
+ * Theme css file to be used
+ * @default "theme.css"
+ */
+ static readonly THEME: string = "themes/theme.css";
+
+ /**
+ * The base URL of the frontend service for linking to replies/quotes/accounts etc.
+ * @default "https://deer.social" // or https://bsky.app if you're boring
+ */
+ static readonly FRONTEND_URL: string = "https://deer.social";
+
+ /**
+ * Maximum number of posts to fetch from the PDS per request
+ * Should be around 20 for about 10 users on the pds
+ * The more users you have, the lower the number should be
+ * since sorting is slow and is done on the frontend
+ * @default 20
+ */
+ static readonly MAX_POSTS: number = 20;
+
+ /**
+ * Footer text for the dashboard, you probably want to change this. Supports HTML.
+ * @default "Source (github mirror)"
+ */
+ static readonly FOOTER_TEXT: string =
+ "Source (github mirror)";
+
+ /**
+ * Whether to show the posts with timestamps that are in the future.
+ * @default false
+ */
+ static readonly SHOW_FUTURE_POSTS: boolean = false;
+}
diff --git a/src/App.svelte b/src/App.svelte
index c6e7534..3ce393b 100644
--- a/src/App.svelte
+++ b/src/App.svelte
@@ -64,90 +64,5 @@
diff --git a/src/app.css b/src/app.css
index 50da734..cb315e4 100644
--- a/src/app.css
+++ b/src/app.css
@@ -1,88 +1,4 @@
-@font-face {
- font-family: "ProggyClean";
- src: url(https://witchcraft.systems/ProggyCleanNerdFont-Regular.ttf);
-}
-
-:root {
- --link-color: #646cff;
- --link-hover-color: #535bf2;
- --background-color: #12082b;
- --header-background-color: #1f1145;
- --content-background-color: #0d0620;
- --text-color: white;
- --border-color: #8054f0;
- --indicator-inactive-color: #4a4a4a;
- --indicator-active-color: #8054f0;
-}
-
-::-webkit-scrollbar {
- width: 0px;
- background: transparent;
- padding: 0;
- margin: 0;
-}
-::-webkit-scrollbar-thumb {
- background: transparent;
- border-radius: 0;
-}
-::-webkit-scrollbar-track {
- background: transparent;
- border-radius: 0;
-}
-::-webkit-scrollbar-corner {
- background: transparent;
- border-radius: 0;
-}
-::-webkit-scrollbar-button {
- background: transparent;
- border-radius: 0;
-}
-* {
- scrollbar-width: none;
- scrollbar-color: transparent transparent;
- -ms-overflow-style: none; /* IE and Edge */
- -webkit-overflow-scrolling: touch;
- -webkit-scrollbar: none; /* Safari */
-}
-
-a {
- font-weight: 500;
- color: var(--link-color);
- text-decoration: inherit;
-}
-a:hover {
- color: var(--link-hover-color);
- text-decoration: underline;
-}
-
+@import url('./themes/colors.css');
body {
- margin: 0;
- display: flex;
- place-items: center;
- min-width: 320px;
- min-height: 100vh;
- background-color: var(--background-color);
- font-family: "ProggyClean", monospace;
- font-size: 24px;
- color: var(--text-color);
- border-color: var(--border-color);
- overflow-wrap: break-word;
- word-wrap: normal;
- word-break: break-word;
- hyphens: none;
-}
-
-h1 {
- font-size: 3.2em;
- line-height: 1.1;
-}
-
-#app {
- max-width: 1400px;
- width: 100%;
- margin: 0;
- padding: 0;
- margin-left: auto;
- margin-right: auto;
- text-align: center;
-}
+ background-color: red;
+}
\ No newline at end of file
diff --git a/src/lib/AccountComponent.svelte b/src/lib/AccountComponent.svelte
index 880db3f..3f12cf7 100644
--- a/src/lib/AccountComponent.svelte
+++ b/src/lib/AccountComponent.svelte
@@ -20,30 +20,5 @@
diff --git a/src/lib/PostComponent.svelte b/src/lib/PostComponent.svelte
index 43ad667..1cacc28 100644
--- a/src/lib/PostComponent.svelte
+++ b/src/lib/PostComponent.svelte
@@ -71,7 +71,7 @@
>
{post.authorHandle}@{post.authorHandle} diff --git a/themes/default/theme.css b/themes/default/theme.css new file mode 100644 index 0000000..f1182d2 --- /dev/null +++ b/themes/default/theme.css @@ -0,0 +1,422 @@ +/* Generic Default Theme for pds-dash */ + +:root { + /* Color overrides, edit to whatever you want */ + --link-color: #3b82f6; + --link-hover-color: #2563eb; + --time-color: #8b5cf6; + --background-color: #f9fafb; + --header-background-color: #ffffff; + --content-background-color: #ffffff; + --text-color: #1f2937; + --border-color: #e5e7eb; + --indicator-inactive-color: #d1d5db; + --indicator-active-color: #6366f1; + --card-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + --hover-bg: #f3f4f6; + --button-bg: #f9fafb; + --button-hover: #f3f4f6; +} + + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; + background-color: var(--background-color); + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif; + font-size: 18px; + line-height: 1.5; + color: var(--text-color); + border-color: var(--border-color); + overflow-wrap: break-word; + word-break: break-word; + hyphens: none; +} + +a { + font-weight: 500; + color: var(--link-color); + text-decoration: none; + transition: color 0.15s ease; +} +a:hover { + color: var(--link-hover-color); +} + +h1 { + font-size: 2.5em; + line-height: 1.2; + font-weight: 700; +} + +#app { + max-width: 1400px; + width: 100%; + margin: 0 auto; + padding: 0; + text-align: center; +} + +/* Post Component */ +#postContainer { + display: flex; + flex-direction: column; + border-radius: 12px; + border: 1px solid var(--border-color); + background-color: var(--content-background-color); + margin-bottom: 20px; + overflow-wrap: break-word; + overflow: hidden; + box-shadow: var(--card-shadow); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +#postContainer:hover { + transform: translateY(-2px); + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); +} + +#postHeader { + display: flex; + flex-direction: row; + align-items: center; + justify-content: start; + background-color: var(--header-background-color); + padding: 12px 16px; + height: 60px; + border-bottom: 1px solid var(--border-color); + font-weight: 600; + overflow-wrap: break-word; +} + +#displayName { + display: block; + color: var(--text-color); + font-size: 1.1em; + padding: 0; + margin: 0 0 2px 0; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + width: 100%; + letter-spacing: -0.01em; +} + +#handle { + display: flex; + align-items: center; + color: #6b7280; + font-size: 0.85em; + font-weight: 400; + padding: 0; + margin: 0; + gap: 8px; +} + +#postLink { + color: var(--time-color); + font-size: 0.85em; + padding: 0; + margin: 0; + opacity: 0.9; +} + +#postContent { + display: flex; + text-align: start; + flex-direction: column; + padding: 16px; + background-color: var(--content-background-color); + color: var(--text-color); + overflow-wrap: break-word; + white-space: pre-line; + line-height: 1.6; +} + +#replyingText, #quotingText { + font-size: 0.8em; + margin: 0; + padding: 0 0 10px 0; + color: #6b7280; +} + +#postText { + margin: 0 0 8px 0; + padding: 0; + overflow-wrap: break-word; + word-break: break-word; + hyphens: none; + font-size: 1.05em; +} + +#headerText { + margin-left: 12px; + font-size: 0.9em; + text-align: start; + word-break: break-word; + max-width: 80%; + max-height: 95%; + overflow: hidden; + align-self: flex-start; + margin-top: auto; + margin-bottom: auto; +} + +#carouselContainer { + position: relative; + width: 100%; + margin-top: 12px; + display: flex; + flex-direction: column; + align-items: center; + border-radius: 8px; + overflow: hidden; +} + +#carouselControls { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + max-width: 500px; + margin-top: 10px; +} + +#carouselIndicators { + display: flex; + gap: 6px; +} + +.indicator { + width: 6px; + height: 6px; + background-color: var(--indicator-inactive-color); + border-radius: 50%; + transition: background-color 0.2s ease, transform 0.2s ease; +} + +.indicator.active { + background-color: var(--indicator-active-color); + transform: scale(1.3); +} + +#prevBtn, +#nextBtn { + background-color: var(--button-bg); + color: var(--text-color); + border: 1px solid var(--border-color); + width: 32px; + height: 32px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; + transition: background-color 0.15s ease, transform 0.15s ease; + font-size: 16px; +} + +#prevBtn:hover:not(:disabled), +#nextBtn:hover:not(:disabled) { + background-color: var(--button-hover); + transform: scale(1.05); +} + +#prevBtn:disabled, +#nextBtn:disabled { + opacity: 0.4; + cursor: not-allowed; +} + +#embedVideo { + width: 100%; + max-width: 500px; + margin-top: 12px; + align-self: center; + border-radius: 8px; + overflow: hidden; +} + +#embedImages { + min-width: min(100%, 500px); + max-width: min(100%, 500px); + max-height: 500px; + object-fit: contain; + margin: 0; + border-radius: 8px; +} + +/* Account Component */ +#accountContainer { + display: flex; + text-align: start; + align-items: center; + background-color: var(--content-background-color); + padding: 12px; + margin-bottom: 15px; + border: 1px solid var(--border-color); + border-radius: 12px; + transition: background-color 0.15s ease; +} + +#accountContainer:hover { + background-color: var(--hover-bg); +} + +#accountName { + margin-left: 12px; + font-size: 0.95em; + max-width: 80%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-weight: 500; +} + +#avatar { + width: 48px; + height: 48px; + margin: 0; + object-fit: cover; + border-radius: 50%; + border: 2px solid white; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); +} + +/* App.Svelte Layout */ +#Content { + display: flex; + width: 100%; + height: 100%; + flex-direction: row; + justify-content: space-between; + align-items: center; + background-color: var(--background-color); + color: var(--text-color); + gap: 24px; +} + +#Feed { + overflow-y: auto; + width: 65%; + height: 100vh; + padding-right: 16px; + align-self: flex-start; +} + +#spacer { + padding: 0; + margin: 0; + height: 10vh; + width: 100%; +} + +#Account { + width: 35%; + display: flex; + flex-direction: column; + border: 1px solid var(--border-color); + background-color: var(--content-background-color); + max-height: 80vh; + padding: 24px; + margin-left: 16px; + border-radius: 12px; + box-shadow: var(--card-shadow); +} + +#accountsList { + display: flex; + flex-direction: column; + overflow-y: auto; + height: 100%; + width: 100%; + padding: 8px 0; + margin: 0; +} + +#Header { + text-align: center; + font-size: 1.8em; + margin-bottom: 16px; + font-weight: 700; + background: linear-gradient(to right, #3b82f6, #8b5cf6); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +/* Mobile Styles */ +@media screen and (max-width: 768px) { + #Content { + flex-direction: column; + width: auto; + padding: 12px; + margin-top: 0; + } + + #Account { + width: calc(100% - 32px); + padding: 16px; + margin-bottom: 20px; + margin-left: 0; + margin-right: 0; + height: auto; + order: -1; + } + + #Feed { + width: 100%; + margin: 0; + padding: 0; + overflow-y: visible; + } + + #spacer { + height: 5vh; + } + + body { + font-size: 16px; + } + + #postHeader { + padding: 10px; + height: auto; + min-height: 50px; + } +} + +/* Scrollbar Styles */ +::-webkit-scrollbar { + width: 0px; + background: transparent; + padding: 0; + margin: 0; +} +::-webkit-scrollbar-thumb { + background: transparent; + border-radius: 0; +} +::-webkit-scrollbar-track { + background: transparent; + border-radius: 0; +} +::-webkit-scrollbar-corner { + background: transparent; + border-radius: 0; +} +::-webkit-scrollbar-button { + background: transparent; + border-radius: 0; +} + +* { + scrollbar-width: none; + scrollbar-color: transparent transparent; + -ms-overflow-style: none; /* IE and Edge */ + -webkit-overflow-scrolling: touch; + -webkit-scrollbar: none; /* Safari */ +} \ No newline at end of file diff --git a/themes/witchcraft/theme.css b/themes/witchcraft/theme.css new file mode 100644 index 0000000..1f9cb00 --- /dev/null +++ b/themes/witchcraft/theme.css @@ -0,0 +1,374 @@ +@font-face { + font-family: "ProggyClean"; + src: url(https://witchcraft.systems/ProggyCleanNerdFont-Regular.ttf); +} + +:root { + /* Color overrides, edit to whatever you want */ + --primary-h: 260; /* Hue */ + + --link-color: hsl(calc(var(--primary-h) - 30), 75%, 60%); + --link-hover-color: hsl(calc(var(--primary-h) - 30), 75%, 50%); + --background-color: hsl(var(--primary-h), 75%, 10%); + --header-background-color: hsl(var(--primary-h), 75%, 18%); + --content-background-color: hsl(var(--primary-h), 75%, 8%); + --text-color: #fff; + --border-color: hsl(var(--primary-h), 75%, 60%); + --indicator-inactive-color: #4a4a4a; + --indicator-active-color: var(--border-color); +} + + +a { + font-weight: 500; + color: var(--link-color); + text-decoration: inherit; +} +a:hover { + color: var(--link-hover-color); + text-decoration: underline; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; + background-color: var(--background-color); + font-family: "ProggyClean", monospace; + font-size: 24px; + color: var(--text-color); + border-color: var(--border-color); + overflow-wrap: break-word; + word-wrap: normal; + word-break: break-word; + hyphens: none; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +#app { + max-width: 1400px; + width: 100%; + margin: 0; + padding: 0; + margin-left: auto; + margin-right: auto; + text-align: center; +} + +/* Post Component */ +a:hover { + text-decoration: underline; +} +#postContainer { + display: flex; + flex-direction: column; + border: 1px solid var(--border-color); + background-color: var(--background-color); + margin-bottom: 15px; + overflow-wrap: break-word; +} +#postHeader { + display: flex; + flex-direction: row; + align-items: center; + justify-content: start; + background-color: var(--header-background-color); + padding: 0px 0px; + height: fit-content; + border-bottom: 1px solid var(--border-color); + font-weight: bold; + overflow-wrap: break-word; + height: 60px; +} +#displayName { + display: block; + color: var(--text-color); + font-size: 1.2em; + padding: 0; + margin: 0; + overflow-wrap: normal; + word-wrap: break-word; + word-break: break-word; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + width: 100%; +} +#handle { + display: block; + color: var(--border-color); + font-size: 0.8em; + padding: 0; + margin: 0; +} + +#postLink { + color: var(--border-color); + font-size: 0.8em; + padding: 0; + margin: 0; +} +#postContent { + display: flex; + text-align: start; + flex-direction: column; + padding: 10px; + background-color: var(--content-background-color); + color: var(--text-color); + overflow-wrap: break-word; + white-space: pre-line; +} +#replyingText { + font-size: 0.7em; + margin: 0; + padding: 0; + padding-bottom: 5px; +} +#quotingText { + font-size: 0.7em; + margin: 0; + padding: 0; + padding-bottom: 5px; +} +#postText { + margin: 0; + padding: 0; + overflow-wrap: break-word; + word-wrap: normal; + word-break: break-word; + hyphens: none; +} +#headerText { + margin-left: 10px; + font-size: 0.9em; + text-align: start; + word-break: break-word; + max-width: 80%; + max-height: 95%; + overflow: hidden; + align-self: flex-start; + margin-top: auto; + margin-bottom: auto; +} +#avatar { + height: 60px; + width: 60px; + margin: 0px; + margin-left: 0px; + overflow: hidden; + object-fit: cover; + border-right: var(--border-color) 1px solid; +} +#carouselContainer { + position: relative; + width: 100%; + margin-top: 10px; + display: flex; + flex-direction: column; + align-items: center; +} +#carouselControls { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + max-width: 500px; + margin-top: 5px; +} +#carouselIndicators { + display: flex; + gap: 5px; +} +.indicator { + width: 8px; + height: 8px; + background-color: var(--indicator-inactive-color); +} +.indicator.active { + background-color: var(--indicator-active-color); +} +#prevBtn, +#nextBtn { + background-color: rgba(31, 17, 69, 0.7); + color: var(--text-color); + border: 1px solid var(--border-color); + width: 30px; + height: 30px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; +} +#prevBtn:disabled, +#nextBtn:disabled { + opacity: 0.5; + cursor: not-allowed; +} +#embedVideo { + width: 100%; + max-width: 500px; + margin-top: 10px; + align-self: center; +} + +#embedImages { + min-width: min(100%, 500px); + max-width: min(100%, 500px); + max-height: 500px; + object-fit: contain; + + margin: 0; +} + +/* Account Component */ +#accountContainer { + display: flex; + text-align: start; + align-items: center; + background-color: var(--background-color); + padding: 0px; + margin-bottom: 15px; + border: 1px solid var(--border-color); +} +#accountName { + margin-left: 10px; + font-size: 0.9em; + max-width: 80%; + + /* replace overflow with ellipsis */ + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +#avatar { + width: 50px; + height: 50px; + margin: 0px; + object-fit: cover; + border-right: var(--border-color) 1px solid; +} + +/* App.Svelte */ +/* desktop style */ + +#Content { + display: flex; + /* split the screen in half, left for accounts, right for posts */ + width: 100%; + height: 100%; + flex-direction: row; + justify-content: space-between; + align-items: center; + background-color: var(--background-color); + color: var(--text-color); +} +#Feed { + overflow-y: scroll; + width: 65%; + height: 100vh; + padding: 20px; + padding-bottom: 0; + padding-top: 0; + margin-top: 0; + margin-bottom: 0; +} +#spacer { + padding: 0; + margin: 0; + height: 10vh; + width: 100%; +} +#Account { + width: 35%; + display: flex; + flex-direction: column; + border: 1px solid var(--border-color); + background-color: var(--content-background-color); + height: 80vh; + padding: 20px; + margin-left: 20px; +} +#accountsList { + display: flex; + flex-direction: column; + overflow-y: scroll; + height: 100%; + width: 100%; + padding: 0px; + margin: 0px; +} + +#Header { + text-align: center; + font-size: 2em; + margin-bottom: 20px; +} + +/* mobile style */ +@media screen and (max-width: 600px) { + #Content { + flex-direction: column; + width: auto; + padding-left: 0px; + padding-right: 0px; + margin-top: 5%; + } + #Account { + width: 85%; + padding-left: 5%; + padding-right: 5%; + margin-bottom: 20px; + margin-left: 5%; + margin-right: 5%; + height: auto; + } + #Feed { + width: 95%; + margin: 0px; + margin-left: 10%; + margin-right: 10%; + padding: 0px; + overflow-y: visible; + } + + #spacer { + height: 0; + } +} + +::-webkit-scrollbar { + width: 0px; + background: transparent; + padding: 0; + margin: 0; +} +::-webkit-scrollbar-thumb { + background: transparent; + border-radius: 0; +} +::-webkit-scrollbar-track { + background: transparent; + border-radius: 0; +} +::-webkit-scrollbar-corner { + background: transparent; + border-radius: 0; +} +::-webkit-scrollbar-button { + background: transparent; + border-radius: 0; +} + +* { + scrollbar-width: none; + scrollbar-color: transparent transparent; + -ms-overflow-style: none; /* IE and Edge */ + -webkit-overflow-scrolling: touch; + -webkit-scrollbar: none; /* Safari */ +} \ No newline at end of file diff --git a/theming.ts b/theming.ts new file mode 100644 index 0000000..3b5964b --- /dev/null +++ b/theming.ts @@ -0,0 +1,32 @@ +import { Plugin } from 'vite'; +import { Config } from './config'; + + +// Replaces app.css with the contents of the file specified in the +// config file. +export const themePlugin = (): Plugin => { + const themeFolder = Config.THEME; + console.log(`Using theme folder: ${themeFolder}`); + return { + name: 'theme-generator', + enforce: 'pre', // Ensure this plugin runs first + transform(code, id) { + if (id.endsWith('app.css')) { + // Read the theme file and replace the contents of app.css with it + // Needs full path to the file + const themeCode = Deno.readTextFileSync(Deno.cwd() + '/themes/' + themeFolder + '/theme.css'); + // Replace the contents of app.css with the theme code + + // and add a comment at the top + const themeComment = `/* Generated from ${themeFolder} */\n`; + const themeCodeWithComment = themeComment + themeCode; + // Return the theme code as the new contents of app.css + return { + code: themeCodeWithComment, + map: null, + }; + } + return null; + } + }; +}; \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts index 20d2272..96d3c8c 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,7 +1,11 @@ import { defineConfig } from "vite"; import { svelte } from "@sveltejs/vite-plugin-svelte"; +import { themePlugin } from "./theming"; // https://vite.dev/config/ export default defineConfig({ - plugins: [svelte()], + plugins: [ + themePlugin(), + svelte(), + ], });