Compare commits
No commits in common. "e5d8cafd258f249eb1ed3ec542b4a4585c30c180" and "c3e706ed7371fac5d6a74590465c8da2ab60c06b" have entirely different histories.
e5d8cafd25
...
c3e706ed73
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,5 +1,5 @@
|
||||||
**/.DS_Store
|
**/.DS_Store
|
||||||
node_modules/
|
node_modules/
|
||||||
build/
|
dist/
|
||||||
.secret/
|
.secret/
|
||||||
.svelte-kit/
|
.svelte-kit/
|
||||||
|
|
24
README.md
24
README.md
|
@ -1,14 +1,17 @@
|
||||||
# Campfire
|
# space social
|
||||||
|
|
||||||
social media for the galaxy-wide-web! 🌌
|
social media for the galaxy-wide-web! 🌌
|
||||||
|
|
||||||
this is a *very experimental* frontend for browsing the fediverse, built
|
this is a neat experiment in building as much of a fediverse-compatible
|
||||||
from the ground up in svelte!
|
software stack as i can (at least before the crippling weight of the full
|
||||||
|
activitypub spec finally cripples me)
|
||||||
|
|
||||||
|
starting, of course, with a nice frontend! ✨
|
||||||
|
|
||||||
should you choose to play around with this yourself, just know that *many
|
should you choose to play around with this yourself, just know that *many
|
||||||
things are bound not to work!* notably, campfire is currently only being
|
things are bound not to work!* notably, this has only been tested on iceshrimp
|
||||||
battle-tested on mastodon API-compliant instances. anything beyond this
|
and mastodon API-compliant instances. anything beyond this will likely be
|
||||||
will likely be incompatible, and the web console will get very upset.
|
incompatible, and the web console will get very upset.
|
||||||
|
|
||||||
## features
|
## features
|
||||||
|
|
||||||
|
@ -31,17 +34,10 @@ will likely be incompatible, and the web console will get very upset.
|
||||||
- fast account switching
|
- fast account switching
|
||||||
- post editing/deletion
|
- post editing/deletion
|
||||||
- push notifications
|
- push notifications
|
||||||
- ...and potentially much more as development continues!
|
|
||||||
|
|
||||||
## try it out!
|
## try it out!
|
||||||
|
|
||||||
- `git clone` this repo
|
- `git clone` this repo
|
||||||
- `npm install` the dependencies
|
- `npm install` the dependencies
|
||||||
- `npm run dev` to spin up the dev environment
|
- `npm run dev` to spin up the dev environment
|
||||||
|
- have fun! ✨
|
||||||
if you wish to run this in production, you need only `npm run build` and
|
|
||||||
place the static files somewhere accessible by a static webhost, such as
|
|
||||||
nginx or apache! **note:** your web server should attempt to reach
|
|
||||||
`/fallback.html` before erroring out.
|
|
||||||
|
|
||||||
have fun! ✨
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "spacesocial-client",
|
"name": "spacesocial-client",
|
||||||
"version": "0.2.0_rev3",
|
"version": "0.2.0_rev2",
|
||||||
"description": "social media for the galaxy-wide-web! 🌌",
|
"description": "social media for the galaxy-wide-web! 🌌",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
BIN
res/campfire-favicon.afdesign
(Stored with Git LFS)
BIN
res/campfire-favicon.afdesign
(Stored with Git LFS)
Binary file not shown.
BIN
res/campfire-logo.afdesign
(Stored with Git LFS)
BIN
res/campfire-logo.afdesign
(Stored with Git LFS)
Binary file not shown.
BIN
res/spacesocial-logo.afdesign
(Stored with Git LFS)
Normal file
BIN
res/spacesocial-logo.afdesign
(Stored with Git LFS)
Normal file
Binary file not shown.
18
src/app.html
18
src/app.html
|
@ -4,23 +4,7 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<link rel="icon" type="image/png" href="/favicon.png">
|
<link rel="icon" type="image/png" href="/favicon.png">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>space social</title>
|
||||||
<title>Campfire</title>
|
|
||||||
<meta name="description" content="Social media for the galaxy-wide-web!">
|
|
||||||
|
|
||||||
<meta property="og:url" content="https://campfire.bliss.town">
|
|
||||||
<meta property="og:type" content="website">
|
|
||||||
<meta property="og:title" content="Campfire">
|
|
||||||
<meta property="og:description" content="Social media for the galaxy-wide-web!">
|
|
||||||
<meta property="og:image" content="https://campfire.bliss.town/favicon.png">
|
|
||||||
|
|
||||||
<meta name="twitter:card" content="summary_large_image">
|
|
||||||
<meta property="twitter:domain" content="campfire.bliss.town">
|
|
||||||
<meta property="twitter:url" content="https://campfire.bliss.town">
|
|
||||||
<meta name="twitter:title" content="Campfire">
|
|
||||||
<meta name="twitter:description" content="Social media for the galaxy-wide-web!">
|
|
||||||
<meta name="twitter:image" content="https://campfire.bliss.town/favicon.png">
|
|
||||||
|
|
||||||
%sveltekit.head%
|
%sveltekit.head%
|
||||||
</head>
|
</head>
|
||||||
<body data-sveltekit-preload-data="hover">
|
<body data-sveltekit-preload-data="hover">
|
||||||
|
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 14 KiB |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 14 KiB |
29
src/img/spacesocial-logo.svg
Normal file
29
src/img/spacesocial-logo.svg
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg width="100%" height="100%" viewBox="0 0 226 89" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||||
|
<g transform="matrix(0.0592476,0,0,0.0592476,19.3835,-44.4646)">
|
||||||
|
<clipPath id="_clip1">
|
||||||
|
<path d="M3471.16,750.487L3471.16,2249.51L-327.161,2249.51L-327.161,750.487L3471.16,750.487ZM2317.49,1260.74L1795.39,1260.74L1795.39,1763.02L2317.49,1763.02L2317.49,1260.74Z"/>
|
||||||
|
</clipPath>
|
||||||
|
<g clip-path="url(#_clip1)">
|
||||||
|
<g transform="matrix(3.12421,0,0,3.12421,13.4825,-77.5092)">
|
||||||
|
<g id="spinner">
|
||||||
|
<path d="M380,380C476.218,283.782 659.849,234.849 710,285C760.151,335.151 756.844,478.156 634,601C511.156,723.844 358.099,784.099 291,717C249.901,675.901 257.955,619 257.955,619C260.181,637.245 251.818,720.443 352.404,720.443C452.989,720.443 530.426,645.937 610.046,566.318C689.665,486.699 778.651,275.064 635.273,275.064C491.896,275.064 380,380 380,380Z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(44.394,0.545455,-44.394,0.545455,899.136,728.049)">
|
||||||
|
<g id="star-shine" serif:id="star shine">
|
||||||
|
<rect x="383" y="377" width="11" height="11"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="star" transform="matrix(1.45161,0,0,1.45161,531.871,522.581)">
|
||||||
|
<path d="M436.5,384L449.059,417.941L483,430.5L449.059,443.059L436.5,477L423.941,443.059L390,430.5L423.941,417.941L436.5,384Z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(2.67689,0,0,2.67689,-1226.58,-333.741)">
|
||||||
|
<g transform="matrix(13.6363,0,0,13.6363,542.101,145.423)">
|
||||||
|
</g>
|
||||||
|
<text x="457.966px" y="145.423px" style="font-family:'Inter-BoldItalic', 'Inter';font-weight:700;font-style:italic;font-size:13.636px;">space social</text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
|
@ -20,15 +20,6 @@
|
||||||
--accent: #CDA1EC;
|
--accent: #CDA1EC;
|
||||||
--text: #E2DFE3;
|
--text: #E2DFE3;
|
||||||
}
|
}
|
||||||
.light-only {
|
|
||||||
display: none
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (prefers-color-scheme: light) {
|
|
||||||
.dark-only {
|
|
||||||
display: none
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@supports (font-variation-settings: normal) {
|
@supports (font-variation-settings: normal) {
|
||||||
|
@ -58,7 +49,7 @@ a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
#app {
|
#spacesocial-app {
|
||||||
margin: auto 0;
|
margin: auto 0;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -7,10 +7,10 @@ import { get } from 'svelte/store';
|
||||||
|
|
||||||
export async function createApp(host) {
|
export async function createApp(host) {
|
||||||
let form = new FormData();
|
let form = new FormData();
|
||||||
form.append("client_name", "Campfire");
|
form.append("client_name", "space social");
|
||||||
form.append("redirect_uris", `${location.origin}/callback`);
|
form.append("redirect_uris", `${location.origin}`);
|
||||||
form.append("scopes", "read write push");
|
form.append("scopes", "read write push");
|
||||||
form.append("website", "https://campfire.bliss.town");
|
form.append("website", "https://spacesocial.arimelody.me");
|
||||||
|
|
||||||
const res = await fetch(`https://${host}/api/v1/apps`, {
|
const res = await fetch(`https://${host}/api/v1/apps`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
@ -35,7 +35,7 @@ export function getOAuthUrl() {
|
||||||
return `https://${client.instance.host}/oauth/authorize` +
|
return `https://${client.instance.host}/oauth/authorize` +
|
||||||
`?client_id=${client.app.id}` +
|
`?client_id=${client.app.id}` +
|
||||||
"&scope=read+write+push" +
|
"&scope=read+write+push" +
|
||||||
`&redirect_uri=${location.origin}/callback` +
|
`&redirect_uri=${location.origin}` +
|
||||||
"&response_type=code";
|
"&response_type=code";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ export async function getToken(code) {
|
||||||
let form = new FormData();
|
let form = new FormData();
|
||||||
form.append("client_id", client.app.id);
|
form.append("client_id", client.app.id);
|
||||||
form.append("client_secret", client.app.secret);
|
form.append("client_secret", client.app.secret);
|
||||||
form.append("redirect_uri", `${location.origin}/callback`);
|
form.append("redirect_uri", `${location.origin}`);
|
||||||
form.append("grant_type", "authorization_code");
|
form.append("grant_type", "authorization_code");
|
||||||
form.append("code", code);
|
form.append("code", code);
|
||||||
form.append("scope", "read write push");
|
form.append("scope", "read write push");
|
||||||
|
@ -212,6 +212,9 @@ export async function parsePost(data, ancestor_count, with_context) {
|
||||||
let client = get(Client.get());
|
let client = get(Client.get());
|
||||||
let post = new Post();
|
let post = new Post();
|
||||||
|
|
||||||
|
// if (client.instance.capabilities.includes(capabilities.MARKDOWN_CONTENT))
|
||||||
|
// post.text = data.text;
|
||||||
|
// else
|
||||||
post.text = data.content;
|
post.text = data.content;
|
||||||
|
|
||||||
post.reply = null;
|
post.reply = null;
|
||||||
|
@ -220,10 +223,10 @@ export async function parsePost(data, ancestor_count, with_context) {
|
||||||
ancestor_count !== 0
|
ancestor_count !== 0
|
||||||
) {
|
) {
|
||||||
const reply_data = data.reply || await getPost(data.in_reply_to_id, ancestor_count - 1);
|
const reply_data = data.reply || await getPost(data.in_reply_to_id, ancestor_count - 1);
|
||||||
|
post.reply = await parsePost(reply_data, ancestor_count - 1, false);
|
||||||
// if the post returns false, we probably don't have permission to read it.
|
// if the post returns false, we probably don't have permission to read it.
|
||||||
// we'll respect the thread's privacy, and leave it alone :)
|
// we'll respect the thread's privacy, and leave it alone :)
|
||||||
if (!reply_data) return false;
|
if (post.reply === false) return false;
|
||||||
post.reply = await parsePost(reply_data, ancestor_count - 1, false);
|
|
||||||
}
|
}
|
||||||
post.boost = data.reblog ? await parsePost(data.reblog, 1, false) : null;
|
post.boost = data.reblog ? await parsePost(data.reblog, 1, false) : null;
|
||||||
|
|
||||||
|
@ -256,7 +259,7 @@ export async function parsePost(data, ancestor_count, with_context) {
|
||||||
post.reply_count = data.replies_count;
|
post.reply_count = data.replies_count;
|
||||||
post.favourite_count = data.favourites_count;
|
post.favourite_count = data.favourites_count;
|
||||||
post.favourited = data.favourited;
|
post.favourited = data.favourited;
|
||||||
post.boosted = data.reblogged;
|
post.boosted = data.boosted;
|
||||||
post.mentions = data.mentions;
|
post.mentions = data.mentions;
|
||||||
post.files = data.media_attachments;
|
post.files = data.media_attachments;
|
||||||
post.url = data.url;
|
post.url = data.url;
|
||||||
|
@ -302,7 +305,7 @@ export async function parseUser(data) {
|
||||||
if (data.acct.includes('@'))
|
if (data.acct.includes('@'))
|
||||||
user.host = data.acct.split('@')[1];
|
user.host = data.acct.split('@')[1];
|
||||||
else
|
else
|
||||||
user.host = client.instance.host;
|
user.host = get(Client.get()).instance.host;
|
||||||
|
|
||||||
user.emojis = [];
|
user.emojis = [];
|
||||||
data.emojis.forEach(emoji_data => {
|
data.emojis.forEach(emoji_data => {
|
||||||
|
@ -312,7 +315,7 @@ export async function parseUser(data) {
|
||||||
user.emojis.push(parseEmoji(emoji_data));
|
user.emojis.push(parseEmoji(emoji_data));
|
||||||
});
|
});
|
||||||
|
|
||||||
client.putCacheUser(user);
|
get(Client.get()).putCacheUser(user);
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { get, writable } from 'svelte/store';
|
||||||
|
|
||||||
let client = writable(false);
|
let client = writable(false);
|
||||||
|
|
||||||
const save_name = "campfire";
|
const save_name = "spacesocial";
|
||||||
|
|
||||||
export class Client {
|
export class Client {
|
||||||
instance;
|
instance;
|
||||||
|
@ -15,7 +15,6 @@ export class Client {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.instance = null;
|
this.instance = null;
|
||||||
this.app = null;
|
this.app = null;
|
||||||
this.user = null;
|
|
||||||
this.cache = {
|
this.cache = {
|
||||||
users: {},
|
users: {},
|
||||||
emojis: {},
|
emojis: {},
|
||||||
|
@ -23,9 +22,10 @@ export class Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
static get() {
|
static get() {
|
||||||
let current = get(client);
|
if (get(client)) return client;
|
||||||
if (current && current.app) return client;
|
|
||||||
let new_client = new Client();
|
let new_client = new Client();
|
||||||
|
if (typeof window !== typeof undefined)
|
||||||
|
window.peekie = new_client;
|
||||||
new_client.load();
|
new_client.load();
|
||||||
client.set(new_client);
|
client.set(new_client);
|
||||||
return client;
|
return client;
|
||||||
|
@ -44,13 +44,13 @@ export class Client {
|
||||||
if (this.instance.type == server_types.UNSUPPORTED) {
|
if (this.instance.type == server_types.UNSUPPORTED) {
|
||||||
console.warn(`Server ${host} is unsupported - ${data.version}`);
|
console.warn(`Server ${host} is unsupported - ${data.version}`);
|
||||||
if (!confirm(
|
if (!confirm(
|
||||||
`This app does not officially support ${host}. ` +
|
`This app does not officially support ${host}. ` +
|
||||||
`Things may break, or otherwise not work as epxected! ` +
|
`Things may break, or otherwise not work as epxected! ` +
|
||||||
`Are you sure you wish to continue?`
|
`Are you sure you wish to continue?`
|
||||||
)) return false;
|
)) return false;
|
||||||
} else {
|
} else {
|
||||||
console.log(`Server is "${this.instance.type}" (or compatible) with capabilities: [${this.instance.capabilities}].`);
|
console.log(`Server is "${this.instance.type}" (or compatible) with capabilities: [${this.instance.capabilities}].`);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.app = await api.createApp(host);
|
this.app = await api.createApp(host);
|
||||||
|
|
||||||
|
@ -85,21 +85,11 @@ export class Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
async verifyCredentials() {
|
async verifyCredentials() {
|
||||||
if (this.user) return this.user;
|
|
||||||
if (!this.app || !this.app.token) {
|
|
||||||
this.user = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const data = await api.verifyCredentials();
|
const data = await api.verifyCredentials();
|
||||||
if (!data) {
|
if (!data) return false;
|
||||||
this.user = false;
|
this.user = await api.parseUser(data);
|
||||||
return false;
|
client.set(this);
|
||||||
}
|
return data;
|
||||||
await client.update(async c => {
|
|
||||||
c.user = await api.parseUser(data);
|
|
||||||
console.log(`Logged in as @${c.user.username}@${c.user.host}`);
|
|
||||||
});
|
|
||||||
return this.user;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getTimeline(last_post_id) {
|
async getTimeline(last_post_id) {
|
||||||
|
|
|
@ -4,14 +4,13 @@ import { parsePost } from '$lib/client/api.js';
|
||||||
|
|
||||||
export let posts = writable([]);
|
export let posts = writable([]);
|
||||||
|
|
||||||
|
let client = get(Client.get());
|
||||||
let loading = false;
|
let loading = false;
|
||||||
|
|
||||||
export async function getTimeline(clean) {
|
export async function getTimeline(clean) {
|
||||||
if (loading) return; // no spamming!!
|
if (loading) return; // no spamming!!
|
||||||
loading = true;
|
loading = true;
|
||||||
|
|
||||||
let client = get(Client.get());
|
|
||||||
|
|
||||||
let timeline_data;
|
let timeline_data;
|
||||||
if (clean || get(posts).length === 0) timeline_data = await client.getTimeline()
|
if (clean || get(posts).length === 0) timeline_data = await client.getTimeline()
|
||||||
else timeline_data = await client.getTimeline(get(posts)[get(posts).length - 1].id);
|
else timeline_data = await client.getTimeline(get(posts)[get(posts).length - 1].id);
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
<script>
|
<script>
|
||||||
import Logo from '$lib/../img/CampfireLogo.svelte';
|
import Logo from '$lib/../img/spacesocial-logo.svg';
|
||||||
import Button from './Button.svelte';
|
import Button from './Button.svelte';
|
||||||
import Feed from './Feed.svelte';
|
import Feed from './Feed.svelte';
|
||||||
import { Client } from '$lib/client/client.js';
|
import { Client } from '$lib/client/client.js';
|
||||||
import { play_sound } from '$lib/sound.js';
|
import { play_sound } from '$lib/sound.js';
|
||||||
import { getTimeline } from '$lib/timeline.js';
|
import { getTimeline } from '$lib/timeline.js';
|
||||||
import { goto } from '$app/navigation';
|
|
||||||
import { get } from 'svelte/store';
|
|
||||||
|
|
||||||
const VERSION = APP_VERSION;
|
const VERSION = APP_VERSION;
|
||||||
|
|
||||||
let client = false;
|
let client = false;
|
||||||
Client.get().subscribe(c => {
|
Client.get().subscribe(c => {
|
||||||
client = c;
|
client = c;
|
||||||
|
@ -27,29 +25,26 @@
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
goto("/");
|
location = "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
async function log_out() {
|
function log_out() {
|
||||||
if (!confirm("This will log you out. Are you sure?")) return;
|
if (!confirm("This will log you out. Are you sure?")) return;
|
||||||
await get(Client.get()).logout();
|
client.logout().then(() => {
|
||||||
goto("/");
|
location = "/";
|
||||||
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="navigation">
|
<div id="navigation">
|
||||||
{#if client.instance && client.instance.icon_url && client.instance.banner_url}
|
<header id="instance-header"> <!-- style={`background-image: url(${banner_url})`}> -->
|
||||||
<header class="instance-header" style="background-image: url({client.instance.banner_url})">
|
<!-- <img src={icon_url} class="instance-icon" height="92px" aria-hidden="true"> -->
|
||||||
<img src={client.instance.icon_url} class="instance-icon" height="92px" aria-hidden="true">
|
<div class="instance-icon instance-icon-mask" style={`mask-image: url(${Logo})`} height="92px" aria-hidden="true">
|
||||||
</header>
|
<!-- <img src={Logo} class="instance-icon" height="92px" aria-hidden="true"> -->
|
||||||
{:else}
|
</header>
|
||||||
<header class="instance-header">
|
|
||||||
<Logo />
|
|
||||||
</header>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div id="nav-items">
|
<div id="nav-items">
|
||||||
<Button label="Timeline" on:click={() => goTimeline()} active={client.user}>🖼️ Timeline</Button>
|
<Button label="Timeline" on:click={() => goTimeline()} active>🖼️ Timeline</Button>
|
||||||
<Button label="Notifications" disabled>
|
<Button label="Notifications" disabled>
|
||||||
🔔 Notifications
|
🔔 Notifications
|
||||||
{#if notification_count}
|
{#if notification_count}
|
||||||
|
@ -89,7 +84,7 @@
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<span class="version">
|
<span class="version">
|
||||||
campfire v{VERSION}
|
space social v{VERSION}
|
||||||
<br>
|
<br>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://git.arimelody.me/ari/spacesocial-client">source</a></li>
|
<li><a href="https://git.arimelody.me/ari/spacesocial-client">source</a></li>
|
||||||
|
@ -109,7 +104,7 @@
|
||||||
background-color: var(--bg-800);
|
background-color: var(--bg-800);
|
||||||
}
|
}
|
||||||
|
|
||||||
.instance-header {
|
#instance-header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 172px;
|
height: 172px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -123,14 +118,18 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.instance-icon {
|
.instance-icon {
|
||||||
height: 50%;
|
height: 92px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.app-logo) {
|
.instance-icon-mask {
|
||||||
max-width: 80%;
|
width: 80%;
|
||||||
max-height: 80%;
|
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
background-color: var(--text);
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
-webkit-mask-repeat: no-repeat;
|
||||||
|
mask-origin: border-box;
|
||||||
|
-webkit-mask-origin: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
#nav-items {
|
#nav-items {
|
||||||
|
|
|
@ -18,8 +18,9 @@
|
||||||
|
|
||||||
let post_context = undefined;
|
let post_context = undefined;
|
||||||
let post = post_data;
|
let post = post_data;
|
||||||
let is_boost = !!post_data.boost;
|
let is_boost = false;
|
||||||
if (is_boost) {
|
if (post_data.boost) {
|
||||||
|
is_boost = true;
|
||||||
post_context = post_data;
|
post_context = post_data;
|
||||||
post = post_data.boost;
|
post = post_data.boost;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +28,6 @@
|
||||||
function gotoPost() {
|
function gotoPost() {
|
||||||
if (focused) return;
|
if (focused) return;
|
||||||
if (event.key && event.key !== "Enter") return;
|
if (event.key && event.key !== "Enter") return;
|
||||||
console.log(`/post/${post.id}`);
|
|
||||||
goto(`/post/${post.id}`);
|
goto(`/post/${post.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,8 +42,8 @@
|
||||||
console.error(`Failed to boost post ${post.id}`);
|
console.error(`Failed to boost post ${post.id}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
post.boosted = data.reblog ? data.reblog.reblogged : data.boosted;
|
post.boosted = data.boosted;
|
||||||
post.boost_count = data.reblog ? data.reblog.reblogs_count : data.reblogs_count;
|
post.boost_count = data.reblogs_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toggleFavourite() {
|
async function toggleFavourite() {
|
||||||
|
@ -126,8 +126,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="post-actions" aria-label="Post actions" on:click|stopPropagation on:keydown|stopPropagation>
|
<div class="post-actions" aria-label="Post actions" on:click|stopPropagation on:keydown|stopPropagation>
|
||||||
<ActionButton type="reply" label="Reply" bind:count={post.reply_count} sound="post" disabled>🗨️</ActionButton>
|
<ActionButton type="reply" label="Reply" bind:count={post.reply_count} sound="post" disabled>🗨️</ActionButton>
|
||||||
<ActionButton type="boost" label="Boost" on:click={toggleBoost} bind:active={post.boosted} bind:count={post.boost_count} sound="boost">🔁</ActionButton>
|
<ActionButton type="boost" label="Boost" on:click={() => toggleBoost()} bind:active={post.boosted} bind:count={post.boost_count} sound="boost">🔁</ActionButton>
|
||||||
<ActionButton type="favourite" label="Favourite" on:click={toggleFavourite} bind:active={post.favourited} bind:count={post.favourite_count}>⭐</ActionButton>
|
<ActionButton type="favourite" label="Favourite" on:click={() => toggleFavourite()} bind:active={post.favourited} bind:count={post.favourite_count}>⭐</ActionButton>
|
||||||
<ActionButton type="react" label="React" disabled>😃</ActionButton>
|
<ActionButton type="react" label="React" disabled>😃</ActionButton>
|
||||||
<ActionButton type="quote" label="Quote" disabled>🗣️</ActionButton>
|
<ActionButton type="quote" label="Quote" disabled>🗣️</ActionButton>
|
||||||
<ActionButton type="more" label="More" disabled>🛠️</ActionButton>
|
<ActionButton type="more" label="More" disabled>🛠️</ActionButton>
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
let aria_label = post.user.username + '; ' + post.text + '; ' + post.created_at;
|
let aria_label = post.user.username + '; ' + post.text + '; ' + post.created_at;
|
||||||
|
|
||||||
function gotoPost() {
|
function gotoPost() {
|
||||||
|
if (focused) return;
|
||||||
if (event.key && event.key !== "Enter") return;
|
if (event.key && event.key !== "Enter") return;
|
||||||
console.log(`/post/${post.id}`);
|
|
||||||
goto(`/post/${post.id}`);
|
goto(`/post/${post.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,8 +108,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="post-actions" aria-label="Post actions" on:click|stopPropagation on:keydown|stopPropagation>
|
<div class="post-actions" aria-label="Post actions" on:click|stopPropagation on:keydown|stopPropagation>
|
||||||
<ActionButton type="reply" label="Reply" bind:count={post.reply_count} sound="post" disabled>🗨️</ActionButton>
|
<ActionButton type="reply" label="Reply" bind:count={post.reply_count} sound="post" disabled>🗨️</ActionButton>
|
||||||
<ActionButton type="boost" label="Boost" on:click={toggleBoost} bind:active={post.boosted} bind:count={post.boost_count} sound="boost">🔁</ActionButton>
|
<ActionButton type="boost" label="Boost" on:click={() => toggleBoost()} bind:active={post.boosted} bind:count={post.boost_count} sound="boost">🔁</ActionButton>
|
||||||
<ActionButton type="favourite" label="Favourite" on:click={toggleFavourite} bind:active={post.favourited} bind:count={post.favourite_count}>⭐</ActionButton>
|
<ActionButton type="favourite" label="Favourite" on:click={() => toggleFavourite()} bind:active={post.favourited} bind:count={post.favourite_count}>⭐</ActionButton>
|
||||||
<ActionButton type="react" label="React" disabled>😃</ActionButton>
|
<ActionButton type="react" label="React" disabled>😃</ActionButton>
|
||||||
<ActionButton type="quote" label="Quote" disabled>🗣️</ActionButton>
|
<ActionButton type="quote" label="Quote" disabled>🗣️</ActionButton>
|
||||||
<ActionButton type="more" label="More" disabled>🛠️</ActionButton>
|
<ActionButton type="more" label="More" disabled>🛠️</ActionButton>
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
<script>
|
|
||||||
import '$lib/app.css';
|
|
||||||
import Navigation from '$lib/ui/Navigation.svelte';
|
|
||||||
import Widgets from '$lib/ui/Widgets.svelte';
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div id="app">
|
|
||||||
|
|
||||||
<header>
|
|
||||||
<Navigation />
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<slot></slot>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<div id="widgets">
|
|
||||||
<Widgets />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
|
@ -1,15 +0,0 @@
|
||||||
import Feed from '$lib/ui/Feed.svelte';
|
|
||||||
import { Client } from '$lib/client/client.js';
|
|
||||||
import Button from '$lib/ui/Button.svelte';
|
|
||||||
import { get } from 'svelte/store';
|
|
||||||
|
|
||||||
export const prerender = true;
|
|
||||||
export const ssr = false;
|
|
||||||
|
|
||||||
export async function load() {
|
|
||||||
let client = get(Client.get());
|
|
||||||
await client.verifyCredentials();
|
|
||||||
return {
|
|
||||||
client: client
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,30 +1,41 @@
|
||||||
<script>
|
<script>
|
||||||
import Logo from '$lib/../img/CampfireLogo.svelte';
|
import '$lib/app.css';
|
||||||
|
import Navigation from '$lib/ui/Navigation.svelte';
|
||||||
|
import Widgets from '$lib/ui/Widgets.svelte';
|
||||||
import Feed from '$lib/ui/Feed.svelte';
|
import Feed from '$lib/ui/Feed.svelte';
|
||||||
import { Client } from '$lib/client/client.js';
|
import { Client } from '$lib/client/client.js';
|
||||||
import User from '$lib/user/user.js';
|
|
||||||
import Button from '$lib/ui/Button.svelte';
|
import Button from '$lib/ui/Button.svelte';
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
|
|
||||||
export let data;
|
let client = get(Client.get());
|
||||||
|
let ready = client.app;
|
||||||
let client = data.client;
|
let logged_in = ready && client.app.token;
|
||||||
let logged_in = client.user && client.user.constructor === User;
|
|
||||||
let instance_url_error = false;
|
let instance_url_error = false;
|
||||||
let logging_in = false;
|
let logging_in = false;
|
||||||
|
|
||||||
function log_in(event) {
|
if (typeof location !== typeof undefined) {
|
||||||
event.preventDefault();
|
let auth_code = new URLSearchParams(location.search).get("code");
|
||||||
instance_url_error = false;
|
if (auth_code) {
|
||||||
|
client.getToken(auth_code).then(() => {
|
||||||
logging_in = true;
|
client.save();
|
||||||
const host = event.target.host.value;
|
location = location.origin;
|
||||||
|
});
|
||||||
if (!host || host === "") {
|
|
||||||
instance_url_error = "Please enter an instance domain.";
|
|
||||||
logging_in = false;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client.app && client.app.token) {
|
||||||
|
// this triggers the client actually getting the authenticated user's data.
|
||||||
|
client.verifyCredentials().then(res => {
|
||||||
|
if (res) {
|
||||||
|
console.log(`Logged in as @${client.user.username}@${client.user.host}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function log_in(event) {
|
||||||
|
logging_in = true;
|
||||||
|
event.preventDefault();
|
||||||
|
const host = event.target.host.value;
|
||||||
|
|
||||||
client.init(host).then(res => {
|
client.init(host).then(res => {
|
||||||
logging_in = false;
|
logging_in = false;
|
||||||
|
@ -39,49 +50,67 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if logged_in}
|
<div id="spacesocial-app">
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
<h1>Home</h1>
|
<Navigation />
|
||||||
<nav>
|
|
||||||
<Button centered active>Home</Button>
|
|
||||||
<Button centered disabled>Local</Button>
|
|
||||||
<Button centered disabled>Federated</Button>
|
|
||||||
</nav>
|
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<Feed />
|
<main>
|
||||||
{:else}
|
{#if ready}
|
||||||
<form on:submit={log_in} id="login-form">
|
{#if logged_in}
|
||||||
<Logo />
|
<header>
|
||||||
<p>Welcome, fediverse user!</p>
|
<h1>Home</h1>
|
||||||
<p>Please enter your instance domain to log in.</p>
|
<nav>
|
||||||
<div class="input-wrapper">
|
<Button centered active>Home</Button>
|
||||||
<input type="text" id="host" aria-label="instance domain" class={logging_in ? "throb" : ""}>
|
<Button centered disabled>Local</Button>
|
||||||
{#if instance_url_error}
|
<Button centered disabled>Federated</Button>
|
||||||
<p class="error">{instance_url_error}</p>
|
</nav>
|
||||||
{/if}
|
</header>
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<button type="submit" id="login" class={logging_in ? "disabled" : ""}>Log in</button>
|
|
||||||
<p><small>
|
|
||||||
Please note this is
|
|
||||||
<strong><em>extremely experimental software</em></strong>;
|
|
||||||
things are likely to break!
|
|
||||||
<br>
|
|
||||||
If that's all cool with you, welcome aboard!
|
|
||||||
</small></p>
|
|
||||||
|
|
||||||
<p class="form-footer">made with ❤ by <a href="https://bliss.town">bliss town</a>, 2024</p>
|
<Feed />
|
||||||
</form>
|
{:else}
|
||||||
{/if}
|
<div>
|
||||||
|
<form on:submit={log_in} id="login">
|
||||||
|
<h1>Space Social</h1>
|
||||||
|
<p>Welcome, fediverse user!</p>
|
||||||
|
<p>Please enter your instance domain to log in.</p>
|
||||||
|
<div class="input-wrapper">
|
||||||
|
<input type="text" id="host" aria-label="instance domain" class={logging_in ? "throb" : ""}>
|
||||||
|
{#if instance_url_error}
|
||||||
|
<p class="error">{instance_url_error}</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<button type="submit" id="login" class={logging_in ? "disabled" : ""}>Log in</button>
|
||||||
|
<p><small>
|
||||||
|
Please note this is
|
||||||
|
<strong><em>extremely experimental software</em></strong>;
|
||||||
|
things are likely to break!
|
||||||
|
<br>
|
||||||
|
If that's all cool with you, welcome aboard!
|
||||||
|
</small></p>
|
||||||
|
|
||||||
|
<p class="form-footer">made with ❤️ by <a href="https://arimelody.me">ari melody</a>, 2024</p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{:else}
|
||||||
|
<div class="loading throb">
|
||||||
|
<span>just a moment...</span>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<div id="widgets">
|
||||||
|
<Widgets />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
form#login-form {
|
form#login {
|
||||||
height: 100vh;
|
margin: 25vh 0 32px 0;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +165,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
button#login {
|
button#login {
|
||||||
margin: 8px auto;
|
margin: -8px auto 0 auto;
|
||||||
padding: 12px 24px;
|
padding: 12px 24px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
@ -186,7 +215,7 @@
|
||||||
|
|
||||||
.loading {
|
.loading {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100vh;
|
height: 80vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -194,27 +223,21 @@
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
main header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 16px 0 8px 0;
|
margin: 16px 0 8px 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
header h1 {
|
main header h1 {
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
header nav {
|
main header nav {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.app-logo) {
|
|
||||||
height: auto;
|
|
||||||
width: 320px;
|
|
||||||
margin: 8px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
import { Client } from '$lib/client/client.js';
|
|
||||||
import { goto } from '$app/navigation';
|
|
||||||
import { error } from '@sveltejs/kit';
|
|
||||||
import { get } from 'svelte/store';
|
|
||||||
|
|
||||||
export const ssr = false;
|
|
||||||
|
|
||||||
export async function load({ params, url }) {
|
|
||||||
const client = get(Client.get());
|
|
||||||
let auth_code = url.searchParams.get("code");
|
|
||||||
if (auth_code) {
|
|
||||||
client.getToken(auth_code).then(() => {
|
|
||||||
client.save();
|
|
||||||
goto("/");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
error(400, {
|
|
||||||
message: "Bad request"
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
import { error } from '@sveltejs/kit';
|
|
||||||
|
|
||||||
export function load(event) {
|
|
||||||
error(404, 'Not Found');
|
|
||||||
}
|
|
50
src/routes/post/[id]/+layout.svelte
Normal file
50
src/routes/post/[id]/+layout.svelte
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
<script>
|
||||||
|
import Navigation from '$lib/ui/Navigation.svelte';
|
||||||
|
import Widgets from '$lib/ui/Widgets.svelte';
|
||||||
|
import Button from '$lib/ui/Button.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div id="spacesocial-app">
|
||||||
|
|
||||||
|
<header>
|
||||||
|
<Navigation />
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<header>
|
||||||
|
<h1>Home</h1>
|
||||||
|
<nav>
|
||||||
|
<Button centered active>Home</Button>
|
||||||
|
<Button centered disabled>Local</Button>
|
||||||
|
<Button centered disabled>Federated</Button>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<slot></slot>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<div id="widgets">
|
||||||
|
<Widgets />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
main header {
|
||||||
|
width: 100%;
|
||||||
|
margin: 16px 0 8px 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
main header h1 {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
main header nav {
|
||||||
|
margin-left: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -3,11 +3,22 @@ import { Client } from '$lib/client/client.js';
|
||||||
import { parsePost } from '$lib/client/api.js';
|
import { parsePost } from '$lib/client/api.js';
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
|
|
||||||
|
export const prerender = true;
|
||||||
export const ssr = false;
|
export const ssr = false;
|
||||||
|
|
||||||
export async function load({ params }) {
|
export async function load({ params }) {
|
||||||
let client = get(Client.get());
|
let client = get(Client.get());
|
||||||
await client.verifyCredentials();
|
if (client.app && client.app.token) {
|
||||||
|
// this triggers the client actually getting the authenticated user's data.
|
||||||
|
const res = await client.verifyCredentials()
|
||||||
|
if (res) {
|
||||||
|
console.log(`Logged in as @${client.user.username}@${client.user.host}`);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const post_id = params.id;
|
const post_id = params.id;
|
||||||
|
|
||||||
|
|
|
@ -1,57 +1,27 @@
|
||||||
<script>
|
<script>
|
||||||
import '$lib/app.css';
|
import '$lib/app.css';
|
||||||
import Post from '$lib/ui/post/Post.svelte';
|
import Post from '$lib/ui/post/Post.svelte';
|
||||||
import Button from '$lib/ui/Button.svelte';
|
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
$: main_post = data.posts[0];
|
const main_post = data.posts[0];
|
||||||
$: replies = data.posts.slice(1);
|
const replies = data.posts.slice(1);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<header>
|
|
||||||
<h1>Home</h1>
|
|
||||||
<nav>
|
|
||||||
<Button centered active>Home</Button>
|
|
||||||
<Button centered disabled>Local</Button>
|
|
||||||
<Button centered disabled>Federated</Button>
|
|
||||||
</nav>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div id="feed" role="feed">
|
<div id="feed" role="feed">
|
||||||
{#if data.posts.length <= 0}
|
{#if data.posts.length <= 0}
|
||||||
<div class="throb">
|
<div class="throb">
|
||||||
<span>just a moment...</span>
|
<span>just a moment...</span>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
{#key data}
|
|
||||||
<Post post_data={main_post} focused />
|
<Post post_data={main_post} focused />
|
||||||
<br>
|
<br>
|
||||||
{#each replies as post}
|
{#each replies as post}
|
||||||
<Post post_data={post} />
|
<Post post_data={post} />
|
||||||
{/each}
|
{/each}
|
||||||
{/key}
|
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
header {
|
|
||||||
width: 100%;
|
|
||||||
margin: 16px 0 8px 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
header h1 {
|
|
||||||
font-size: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
header nav {
|
|
||||||
margin-left: auto;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feed {
|
#feed {
|
||||||
margin-bottom: 20vh;
|
margin-bottom: 20vh;
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 33 KiB |
Binary file not shown.
Before Width: | Height: | Size: 28 KiB |
|
@ -1,14 +0,0 @@
|
||||||
User-agent: *
|
|
||||||
Disallow: /nobot/
|
|
||||||
Disallow: /private/
|
|
||||||
|
|
||||||
User-agent: GPTBot
|
|
||||||
Disallow: /
|
|
||||||
User-agent: ChatGPT-User
|
|
||||||
Disallow: /
|
|
||||||
|
|
||||||
User-agent: Google-Extended
|
|
||||||
Disallow: /
|
|
||||||
|
|
||||||
User-agent: CCBot
|
|
||||||
Disallow: /
|
|
|
@ -11,8 +11,8 @@ const config = {
|
||||||
adapter: adapter({
|
adapter: adapter({
|
||||||
pages: 'build',
|
pages: 'build',
|
||||||
assets: 'build',
|
assets: 'build',
|
||||||
fallback: "fallback.html",
|
fallback: undefined,
|
||||||
precompress: true,
|
precompress: false,
|
||||||
strict: true,
|
strict: true,
|
||||||
}),
|
}),
|
||||||
version: {
|
version: {
|
||||||
|
|
Loading…
Reference in a new issue