Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
584ab34df6 | ||
|
|
0514c1d982 |
Generated
+14
-14
@@ -273,7 +273,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "assets"
|
name = "assets"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"gpui",
|
"gpui",
|
||||||
@@ -535,7 +535,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "auto_update"
|
name = "auto_update"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gpui",
|
"gpui",
|
||||||
"gpui-updater",
|
"gpui-updater",
|
||||||
@@ -1067,7 +1067,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chat"
|
name = "chat"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"common",
|
"common",
|
||||||
@@ -1089,7 +1089,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chat_ui"
|
name = "chat_ui"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chat",
|
"chat",
|
||||||
@@ -1272,7 +1272,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "common"
|
name = "common"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"dirs 5.0.1",
|
"dirs 5.0.1",
|
||||||
@@ -1400,7 +1400,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "coop"
|
name = "coop"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assets",
|
"assets",
|
||||||
"auto_update",
|
"auto_update",
|
||||||
@@ -1426,7 +1426,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "coop_web"
|
name = "coop_web"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assets",
|
"assets",
|
||||||
"chat",
|
"chat",
|
||||||
@@ -1770,7 +1770,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "device"
|
name = "device"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"common",
|
"common",
|
||||||
@@ -4972,7 +4972,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "person"
|
name = "person"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"common",
|
"common",
|
||||||
@@ -6385,7 +6385,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "settings"
|
name = "settings"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"common",
|
"common",
|
||||||
@@ -6629,7 +6629,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "state"
|
name = "state"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"browser-signer-proxy",
|
"browser-signer-proxy",
|
||||||
@@ -6980,7 +6980,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "theme"
|
name = "theme"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"gpui",
|
"gpui",
|
||||||
@@ -7529,7 +7529,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ui"
|
name = "ui"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"common",
|
"common",
|
||||||
@@ -8925,7 +8925,7 @@ checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "workspace"
|
name = "workspace"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"auto_update",
|
"auto_update",
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ members = ["crates/*", "desktop", "web"]
|
|||||||
default-members = ["desktop"]
|
default-members = ["desktop"]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use gpui_updater::{EngineConfig, GitHubSource, UpdateStatus, Updater, Version};
|
|||||||
use instant::{Duration, Instant};
|
use instant::{Duration, Instant};
|
||||||
|
|
||||||
const COOP_UPDATE_EXPLANATION: &str = "COOP_UPDATE_EXPLANATION";
|
const COOP_UPDATE_EXPLANATION: &str = "COOP_UPDATE_EXPLANATION";
|
||||||
|
const COOP_BUNDLE_TYPE: &str = "COOP_BUNDLE_TYPE";
|
||||||
|
|
||||||
fn get_github_repo_owner() -> String {
|
fn get_github_repo_owner() -> String {
|
||||||
std::env::var("COOP_GITHUB_REPO_OWNER").unwrap_or_else(|_| "reyakov".to_string())
|
std::env::var("COOP_GITHUB_REPO_OWNER").unwrap_or_else(|_| "reyakov".to_string())
|
||||||
@@ -14,18 +15,27 @@ fn get_github_repo_name() -> String {
|
|||||||
std::env::var("COOP_GITHUB_REPO_NAME").unwrap_or_else(|_| "coop".to_string())
|
std::env::var("COOP_GITHUB_REPO_NAME").unwrap_or_else(|_| "coop".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_flatpak_installation() -> bool {
|
/// Whether updates are managed by an external distribution channel
|
||||||
std::env::var("FLATPAK_ID").is_ok() || std::env::var(COOP_UPDATE_EXPLANATION).is_ok()
|
/// (Flatpak/Snap), in which case the in-app updater must not run.
|
||||||
|
fn uses_managed_updates() -> bool {
|
||||||
|
// The Flatpak runtime exports `FLATPAK_ID` inside the sandbox.
|
||||||
|
std::env::var("FLATPAK_ID").is_ok()
|
||||||
|
// Allow opting out of in-app updates via an explicit environment variable.
|
||||||
|
|| std::env::var(COOP_UPDATE_EXPLANATION).is_ok()
|
||||||
|
// The Snap package sets `COOP_BUNDLE_TYPE=snap` (see snapcraft.yaml.in).
|
||||||
|
|| std::env::var(COOP_BUNDLE_TYPE).is_ok_and(|value| value == "snap")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize the auto-update system.
|
/// Initialize the auto-update system.
|
||||||
///
|
///
|
||||||
/// Skips initialization when running as a Flatpak (updates are handled by the
|
/// Skips initialization when updates are handled by an external distribution
|
||||||
/// Flatpak distribution channel). Otherwise creates the global [`AutoUpdater`]
|
/// channel (Flatpak/Snap). Otherwise creates the global [`AutoUpdater`]
|
||||||
/// entity and schedules a check for updates after a 2-minute delay.
|
/// entity and schedules a check for updates after a 2-minute delay.
|
||||||
pub fn init(window: &mut Window, cx: &mut App) {
|
pub fn init(window: &mut Window, cx: &mut App) {
|
||||||
if is_flatpak_installation() {
|
if uses_managed_updates() {
|
||||||
log::info!("Skipping auto-update initialization: App is installed via Flatpak");
|
log::info!(
|
||||||
|
"Skipping auto-update initialization: App is installed via a managed distribution channel (Flatpak/Snap)"
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +67,27 @@ pub struct AutoUpdater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AutoUpdater {
|
impl AutoUpdater {
|
||||||
|
/// Whether auto-update is available for this installation.
|
||||||
|
///
|
||||||
|
/// Returns `false` on managed distribution channels (Flatpak/Snap), where
|
||||||
|
/// updates are handled by the channel and no global updater is created.
|
||||||
|
pub fn is_available(cx: &App) -> bool {
|
||||||
|
cx.try_global::<GlobalAutoUpdater>().is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve the global auto updater instance, if one was initialized.
|
||||||
|
pub fn try_global(cx: &App) -> Option<Entity<Self>> {
|
||||||
|
cx.try_global::<GlobalAutoUpdater>()
|
||||||
|
.map(|global| global.0.clone())
|
||||||
|
}
|
||||||
|
|
||||||
/// Retrieve the global auto updater instance.
|
/// Retrieve the global auto updater instance.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics when auto-update is not available for this installation. Prefer
|
||||||
|
/// [`AutoUpdater::try_global`] when the installation type is not known at
|
||||||
|
/// compile time (e.g. Flatpak/Snap).
|
||||||
pub fn global(cx: &App) -> Entity<Self> {
|
pub fn global(cx: &App) -> Entity<Self> {
|
||||||
cx.global::<GlobalAutoUpdater>().0.clone()
|
cx.global::<GlobalAutoUpdater>().0.clone()
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-16
@@ -380,12 +380,15 @@ impl Workspace {
|
|||||||
self.import_encryption(window, cx);
|
self.import_encryption(window, cx);
|
||||||
}
|
}
|
||||||
Command::Update => {
|
Command::Update => {
|
||||||
let auto_updater = AutoUpdater::global(cx);
|
// No-op on managed distribution channels (Flatpak/Snap) where
|
||||||
auto_updater.update(cx, |this, cx| {
|
// the in-app updater is never initialized.
|
||||||
this.updater.update(cx, |updater, cx| {
|
if let Some(auto_updater) = AutoUpdater::try_global(cx) {
|
||||||
updater.check(cx);
|
auto_updater.update(cx, |this, cx| {
|
||||||
|
this.updater.update(cx, |updater, cx| {
|
||||||
|
updater.check(cx);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -559,7 +562,7 @@ impl Workspace {
|
|||||||
.caret()
|
.caret()
|
||||||
.compact()
|
.compact()
|
||||||
.transparent()
|
.transparent()
|
||||||
.dropdown_menu(move |this, _window, _cx| {
|
.dropdown_menu(move |this, _window, cx| {
|
||||||
let avatar = avatar.clone();
|
let avatar = avatar.clone();
|
||||||
let name = name.clone();
|
let name = name.clone();
|
||||||
|
|
||||||
@@ -593,12 +596,15 @@ impl Workspace {
|
|||||||
IconName::Sun,
|
IconName::Sun,
|
||||||
Box::new(Command::ToggleTheme),
|
Box::new(Command::ToggleTheme),
|
||||||
)
|
)
|
||||||
.separator()
|
// Only offer in-app updates when auto-update is
|
||||||
.menu_with_icon(
|
// enabled (managed channels update themselves).
|
||||||
"Check for Updates",
|
.when(AutoUpdater::is_available(cx), |this| {
|
||||||
IconName::Device,
|
this.separator().menu_with_icon(
|
||||||
Box::new(Command::Update),
|
"Check for Updates",
|
||||||
)
|
IconName::Device,
|
||||||
|
Box::new(Command::Update),
|
||||||
|
)
|
||||||
|
})
|
||||||
.menu_with_icon(
|
.menu_with_icon(
|
||||||
"Settings",
|
"Settings",
|
||||||
IconName::Settings,
|
IconName::Settings,
|
||||||
@@ -610,7 +616,6 @@ impl Workspace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn titlebar_right(&mut self, cx: &mut Context<Self>) -> impl IntoElement {
|
fn titlebar_right(&mut self, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
let updater = AutoUpdater::global(cx);
|
|
||||||
let chat = ChatRegistry::global(cx);
|
let chat = ChatRegistry::global(cx);
|
||||||
let nip4e_enabled = AppSettings::get_nip4e(cx);
|
let nip4e_enabled = AppSettings::get_nip4e(cx);
|
||||||
let nostr = NostrRegistry::global(cx);
|
let nostr = NostrRegistry::global(cx);
|
||||||
@@ -622,13 +627,19 @@ impl Workspace {
|
|||||||
let persons = PersonRegistry::global(cx);
|
let persons = PersonRegistry::global(cx);
|
||||||
let profile = persons.read(cx).get(&public_key, cx);
|
let profile = persons.read(cx).get(&public_key, cx);
|
||||||
let announcement = profile.announcement();
|
let announcement = profile.announcement();
|
||||||
let updater_idle = updater.read(cx).idle(cx);
|
|
||||||
|
// Update status is only shown when auto-update is available. On
|
||||||
|
// managed distribution channels (Flatpak/Snap) no updater exists, so
|
||||||
|
// nothing is rendered.
|
||||||
|
let updater_status = AutoUpdater::try_global(cx).and_then(|updater| {
|
||||||
|
let updater = updater.read(cx);
|
||||||
|
(!updater.idle(cx)).then(|| updater.status(cx))
|
||||||
|
});
|
||||||
|
|
||||||
h_flex()
|
h_flex()
|
||||||
.when(!cx.theme().platform.is_mac(), |this| this.pr_2())
|
.when(!cx.theme().platform.is_mac(), |this| this.pr_2())
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.when(!updater_idle, |this| {
|
.when_some(updater_status, |this, status| {
|
||||||
let status = updater.read(cx).status(cx);
|
|
||||||
this.child(div().text_xs().italic().child(status))
|
this.child(div().text_xs().italic().child(status))
|
||||||
})
|
})
|
||||||
.when(nip4e_enabled, |this| {
|
.when(nip4e_enabled, |this| {
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ product-name = "Coop"
|
|||||||
description = "Chat Freely, Stay Private on Nostr"
|
description = "Chat Freely, Stay Private on Nostr"
|
||||||
identifier = "su.reya.coop"
|
identifier = "su.reya.coop"
|
||||||
category = "SocialNetworking"
|
category = "SocialNetworking"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
out-dir = "../dist"
|
out-dir = "../dist"
|
||||||
before-packaging-command = "cargo build --release"
|
before-packaging-command = "cargo build --release"
|
||||||
resources = ["Cargo.toml", "src"]
|
resources = ["Cargo.toml", "src"]
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
# Snaps built by snapcraft without Snap Store credentials are unsigned and
|
||||||
|
# cannot be installed without bypassing signature checks. Use:
|
||||||
|
# sudo snap install --dangerous ./coop_<version>_<arch>.snap
|
||||||
|
# For signed installs (`snap install coop`), publish via the Snap Store.
|
||||||
name: coop
|
name: coop
|
||||||
title: Coop
|
title: Coop
|
||||||
base: core24
|
base: core24
|
||||||
|
|||||||
@@ -35,3 +35,7 @@ SNAP_NAME="coop_${1}_${ARCH_SUFFIX}.snap"
|
|||||||
snapcraft --destructive-mode --output "$SNAP_NAME"
|
snapcraft --destructive-mode --output "$SNAP_NAME"
|
||||||
|
|
||||||
echo "Created snap package: $SNAP_NAME"
|
echo "Created snap package: $SNAP_NAME"
|
||||||
|
echo ""
|
||||||
|
echo "This snap is unsigned (built without Snap Store credentials)."
|
||||||
|
echo "To install it locally, use:"
|
||||||
|
echo " sudo snap install --dangerous ./$SNAP_NAME"
|
||||||
|
|||||||
+16
-10
@@ -29,23 +29,29 @@ fi
|
|||||||
# Function to update version in a Cargo.toml file
|
# Function to update version in a Cargo.toml file
|
||||||
update_version() {
|
update_version() {
|
||||||
local file="$1"
|
local file="$1"
|
||||||
local backup="${file}.bak"
|
local tmp="${file}.tmp"
|
||||||
|
|
||||||
# Backup the original file
|
# Portable in-place edit. `sed -i` behaves differently on GNU sed (Linux)
|
||||||
cp "$file" "$backup"
|
# and BSD sed (macOS): on macOS `sed -i -E` treats `-E` as the backup
|
||||||
|
# suffix instead of the extended-regex flag, leaving a stray
|
||||||
# More flexible regex that handles various version formats and whitespace
|
# `Cargo.toml-E` behind and never updating the file.
|
||||||
if sed -i -E "s/^[[:space:]]*version[[:space:]]*=[[:space:]]*\"[^\"]+\"/version = \"$NEW_VERSION\"/" "$file"; then
|
# Writing to a temp file and moving it over works on both implementations.
|
||||||
|
if sed -E "s/^[[:space:]]*version[[:space:]]*=[[:space:]]*\"[^\"]+\"/version = \"$NEW_VERSION\"/" "$file" > "$tmp" \
|
||||||
|
&& mv "$tmp" "$file"; then
|
||||||
echo "✓ Updated version to $NEW_VERSION in $file"
|
echo "✓ Updated version to $NEW_VERSION in $file"
|
||||||
else
|
else
|
||||||
echo "Error: Failed to update version in $file"
|
echo "Error: Failed to update version in $file"
|
||||||
# Restore original backup
|
# Remove any partial temp file; the original file is untouched
|
||||||
mv "$backup" "$file"
|
rm -f "$tmp"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Remove the backup file
|
# The substitution can silently match nothing (e.g. a `version.workspace` key),
|
||||||
rm -f "$backup"
|
# so verify the new version actually landed before moving on.
|
||||||
|
if ! grep -q "^[[:space:]]*version[[:space:]]*=[[:space:]]*\"$NEW_VERSION\"" "$file"; then
|
||||||
|
echo "Error: Version line not found/updated in $file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Update both Cargo.toml files
|
# Update both Cargo.toml files
|
||||||
|
|||||||
+16
-1
@@ -15,11 +15,26 @@ if [ "$#" -ne 1 ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Get system architecture (same mapping as script/bundle-snap)
|
||||||
|
ARCH=$(uname -m)
|
||||||
|
case "$ARCH" in
|
||||||
|
x86_64) ARCH_SUFFIX="x86_64" ;;
|
||||||
|
aarch64) ARCH_SUFFIX="aarch64" ;;
|
||||||
|
*) echo "Unsupported architecture: $ARCH"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
snap_file="coop_${1}_${ARCH_SUFFIX}.snap"
|
||||||
|
if [ ! -f "$snap_file" ]; then
|
||||||
|
echo "Snap file not found: $snap_file"
|
||||||
|
echo "Build it first with: script/bundle-snap $1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Rerun as root
|
# Rerun as root
|
||||||
[ "$UID" -eq 0 ] || exec sudo bash -e "$0" "$@"
|
[ "$UID" -eq 0 ] || exec sudo bash -e "$0" "$@"
|
||||||
|
|
||||||
snap remove coop || true
|
snap remove coop || true
|
||||||
mkdir -p snap
|
mkdir -p snap
|
||||||
rm -rf snap/unpacked
|
rm -rf snap/unpacked
|
||||||
unsquashfs -dest snap/unpacked "coop_$1_amd64.snap"
|
unsquashfs -dest snap/unpacked "$snap_file"
|
||||||
snap try --classic snap/unpacked
|
snap try --classic snap/unpacked
|
||||||
|
|||||||
Reference in New Issue
Block a user