5 Commits

Author SHA1 Message Date
c59fba817d ssb: Show the progress indicator more consistently.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 30m54s
2025-07-31 12:48:45 -04:00
c3415ab75c docs: Expose the rest of core to docs.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 31m24s
2025-07-30 20:25:20 -04:00
f1d0151d71 ssb: Make the progress bar more indefinite-looking.
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
2025-07-30 20:04:34 -04:00
3c5c1756d1 ssb: A progress bar experiment. 2025-07-30 19:49:08 -04:00
6a6b65d1b3 build: Update nix config. Start building 0.2025.8, switching to calver.
Some checks failed
Build Tilde Friends / Build-All (push) Has been cancelled
2025-07-30 19:26:26 -04:00
13 changed files with 117 additions and 32 deletions

View File

@@ -16,9 +16,9 @@ MAKEFLAGS += --no-builtin-rules
## LD := Linker.
## ANDROID_SDK := Path to the Android SDK.
VERSION_CODE := 40
VERSION_CODE_IOS := 15
VERSION_NUMBER := 0.0.33
VERSION_CODE := 41
VERSION_CODE_IOS := 16
VERSION_NUMBER := 0.2025.8-wip
VERSION_NAME := This program kills fascists.
IPHONEOS_VERSION_MIN=14.0

View File

@@ -1,5 +1,5 @@
{
"type": "tildefriends-app",
"emoji": "🦀",
"previous": "&DGtlnm5wWRZCgJMF8JsP6VtzNRrd4KLoERJRpFULqOY=.sha256"
"previous": "&nvdIMraZtEjSegUCd4b5hLz6Csn5YNV+vyJWu7QAE3I=.sha256"
}

View File

@@ -25,6 +25,7 @@ class TfElement extends LitElement {
recent_reactions: {type: Array},
is_administrator: {type: Boolean},
stay_connected: {type: Boolean},
progress: {type: Number},
};
}
@@ -56,6 +57,7 @@ class TfElement extends LitElement {
tfrpc.rpc.getHash().then((hash) => self.set_hash(hash));
tfrpc.register(function hashChanged(hash) {
self.set_hash(hash);
self.reset_progress();
});
tfrpc.register(async function notifyNewMessage(id) {
await self.fetch_new_message(id);
@@ -450,7 +452,26 @@ class TfElement extends LitElement {
this.schedule_load_latest();
}
reset_progress() {
if (this.progress === undefined) {
this._progress_start = new Date();
requestAnimationFrame(this.update_progress.bind(this));
}
}
update_progress() {
if (!this.loading_latest &&
!this.loading_latest_scheduled &&
!this.shadowRoot.getElementById('tf-tab-news')?.is_loading()) {
this.progress = undefined;
return;
}
this.progress = (new Date() - this._progress_start).valueOf();
requestAnimationFrame(this.update_progress.bind(this));
}
schedule_load_latest() {
this.reset_progress();
if (!this.loading_latest) {
this.shadowRoot.getElementById('tf-tab-news')?.load_latest();
this.load();
@@ -495,6 +516,7 @@ class TfElement extends LitElement {
async load() {
this.loading_latest = true;
this.reset_progress();
try {
let start_time = new Date();
let whoami = this.whoami;
@@ -603,6 +625,7 @@ class TfElement extends LitElement {
@channelsetunread=${this.channel_set_unread}
@refresh=${this.refresh}
@toggle_stay_connected=${this.toggle_stay_connected}
@loadmessages=${this.reset_progress}
.connections=${this.connections}
.private_messages=${this.private_messages}
.recent_reactions=${this.recent_reactions}
@@ -646,6 +669,7 @@ class TfElement extends LitElement {
async set_tab(tab) {
this.tab = tab;
if (tab === 'news') {
this.schedule_load_latest();
await tfrpc.rpc.setHash('#');
} else if (tab === 'connections') {
await tfrpc.rpc.setHash('#connections');
@@ -751,11 +775,23 @@ class TfElement extends LitElement {
Loading...
</div>`
: this.render_tab();
let progress =
this.progress !== undefined
? html`
<div style="position: absolute; width: 100%" id="progress">
<div
class="w3-theme-l2"
style=${`height: 4px; position: absolute; right: ${Math.cos(this.progress / 250) > 0 ? 'auto' : '0'}; width: ${50 * Math.sin(this.progress / 250) + 50}%`}
></div>
</div>
`
: undefined;
return html`
<div
style="width: 100vw; min-height: 100vh; height: 100vh; display: flex; flex-direction: column"
class="w3-theme-dark"
>
${progress}
<div style="flex: 0 0">${tabs}</div>
<div style="flex: 1 1; overflow: auto; contain: layout">
${contents}

View File

@@ -106,6 +106,12 @@ class TfTabNewsFeedElement extends LitElement {
}
async fetch_messages(start_time, end_time) {
this.dispatchEvent(
new CustomEvent('loadmessages', {
bubbles: true,
composed: true,
})
);
this.time_loading = [start_time, end_time];
let result;
const k_max_results = 64;

View File

@@ -180,6 +180,10 @@ class TfTabNewsElement extends LitElement {
await this.check_peer_exchange();
}
is_loading() {
return this.shadowRoot?.getElementById('news')?.loading;
}
render_sidebar() {
return html`
<div

View File

@@ -1,7 +1,23 @@
/**
* \file
* \defgroup tfapp Tilde Friends App JS
* Tilde Friends server-side app wrapper.
* @{
*/
/** \cond */
import * as core from './core.js';
let gSessionIndex = 0;
export {App};
/** \endcond */
/** A sequence number of apps. */
let g_session_index = 0;
/**
** App constructor.
** @return An app instance.
*/
function App() {
this._send_queue = [];
this.calls = {};
@@ -9,6 +25,12 @@ function App() {
return this;
}
/**
** Create a function wrapper that when called invokes a function on the app
** itself.
** @param api The function and argument names.
** @return A function.
*/
App.prototype.makeFunction = function (api) {
let self = this;
let result = function () {
@@ -32,6 +54,10 @@ App.prototype.makeFunction = function (api) {
return result;
};
/**
** Send a message to the app.
** @param message The message to send.
*/
App.prototype.send = function (message) {
if (this._send_queue) {
if (this._on_output) {
@@ -46,6 +72,11 @@ App.prototype.send = function (message) {
}
};
/**
** App socket handler.
** @param request The HTTP request of the WebSocket connection.
** @param response The HTTP response.
*/
exports.app_socket = async function socket(request, response) {
let process;
let options = {};
@@ -133,7 +164,7 @@ exports.app_socket = async function socket(request, response) {
options.packageOwner = packageOwner;
options.packageName = packageName;
options.url = message.url;
let sessionId = 'session_' + (gSessionIndex++).toString();
let sessionId = 'session_' + (g_session_index++).toString();
if (blobId) {
if (message.edit_only) {
response.send(
@@ -218,4 +249,4 @@ exports.app_socket = async function socket(request, response) {
response.upgrade(100, {});
};
export {App};
/** @} */

View File

@@ -1,8 +1,14 @@
/**
* TODOC
* TODO: document so we can improve this
* @param {*} url
* @returns
* \file
* \defgroup tfhttp Tilde Friends HTTP Client JS
* Tilde Friends server-side HTTP client.
* @{
*/
/**
* Parse a URL into protocol, host, path, and port parts.
* @param url
* @returns An object of the URL parts.
*/
function parseUrl(url) {
// XXX: Hack.
@@ -16,9 +22,9 @@ function parseUrl(url) {
}
/**
* TODOC
* @param {*} data
* @returns
* Parse an HTTP response into headers and body content.
* @param data The response data, headers and body included.
* @returns headers and body data.
*/
function parseResponse(data) {
let firstLine;
@@ -36,15 +42,15 @@ function parseResponse(data) {
headers[line.substring(colon)] = line.substring(colon + 1);
}
}
return {body: data};
return {headers: headers, body: data};
}
/**
* TODOC
* @param {*} url
* @param {*} options
* @param {*} allowed_hosts
* @returns
* Make an HTTP request.
* @param url The URL.
* @param options Request options.
* @param allowed_hosts List of allowed hosts.
* @return A promise resolved with the response headers and body.
*/
export function fetch(url, options, allowed_hosts) {
let parsed = parseUrl(url);
@@ -111,3 +117,5 @@ export function fetch(url, options, allowed_hosts) {
});
});
}
/** @} */

View File

@@ -15,8 +15,8 @@ let g_next_id = 1;
let g_calls = {};
/**
* TODOC
* @returns
* Check if being called from a browser vs. server-side.
* @return true if called from a browser.
*/
function get_is_browser() {
try {

View File

@@ -25,14 +25,14 @@
}:
pkgs.stdenv.mkDerivation rec {
pname = "tildefriends";
version = "0.0.32";
version = "0.0.33";
src = pkgs.fetchFromGitea {
domain = "dev.tildefriends.net";
owner = "cory";
repo = "tildefriends";
rev = "v${version}";
hash = "sha256-Dk0NOEQIg2LeENySK0+MgpZEtfsClGq6dZL+eOOpE0U=";
hash = "sha256-9D28gmaBTRVyXhY3zZd/W9PsXA1YZt/K69hz41aVP04=";
fetchSubmodules = true;
};

6
flake.lock generated
View File

@@ -20,11 +20,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1750622754,
"narHash": "sha256-kMhs+YzV4vPGfuTpD3mwzibWUE6jotw5Al2wczI0Pv8=",
"lastModified": 1753749649,
"narHash": "sha256-+jkEZxs7bfOKfBIk430K+tK9IvXlwzqQQnppC2ZKFj4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c7ab75210cb8cb16ddd8f290755d9558edde7ee1",
"rev": "1f08a4df998e21f4e8be8fb6fbf61d11a1a5076a",
"type": "github"
},
"original": {

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.unprompted.tildefriends"
android:versionCode="40"
android:versionName="0.0.33">
android:versionCode="41"
android:versionName="0.2025.8-wip">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application

View File

@@ -13,13 +13,13 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.0.33</string>
<string>0.2025.8</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>iPhoneOS</string>
</array>
<key>CFBundleVersion</key>
<string>15</string>
<string>16</string>
<key>DTPlatformName</key>
<string>iphoneos</string>
<key>LSRequiresIPhoneOS</key>

View File

@@ -1,2 +1,2 @@
#define VERSION_NUMBER "0.0.33"
#define VERSION_NUMBER "0.2025.8-wip"
#define VERSION_NAME "This program kills fascists."