#!/usr/bin/env bash # SPDX-License-Identifier: MIT # Viet+ — Vietnamese Input Method Installer set -euo pipefail RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[0;33m'; NC='\033[0m' [ "$EUID" -ne 0 ] && echo -e "${RED}Please run with sudo.${NC}" && exit 1 echo -e "${GREEN}=== Viet+ Installer ===${NC}" # Architecture ARCH=$(uname -m) case "$ARCH" in x86_64) ARCH="amd64" ;; aarch64) ARCH="arm64" ;; *) echo -e "${RED}Unsupported architecture: $ARCH${NC}"; exit 1 ;; esac # Distro [ -f /etc/os-release ] && . /etc/os-release DISTRO="${ID:-unknown}" echo "Detected: $DISTRO ($ARCH)" install_runtime_deps() { echo "Installing runtime dependencies..." case "$DISTRO" in ubuntu|debian|linuxmint|mint|pop|neon|zorin|elementary) export DEBIAN_FRONTEND=noninteractive apt-get update -y apt-get install -y libevdev2 libdbus-1-3 libx11-6 libxtst6 \ libwayland-client0 xclip wl-clipboard curl ;; fedora|rhel|centos) dnf install -y libevdev libX11 libXtst dbus-libs libwayland-client xclip wl-clipboard curl ;; arch|manjaro|cachyos|endeavouros|garuda|artix) pacman -Sy --needed --noconfirm libevdev libx11 libxtst dbus \ libwayland xclip wl-clipboard curl ;; *) echo -e "${YELLOW}Unsupported: $DISTRO. Install deps manually.${NC}" ;; esac } install_runtime_deps echo "Fetching latest release..." RELEASE_JSON=$(curl -sSfL "https://api.github.com/repos/vndangkhoa/vietc/releases/latest" 2>/dev/null || echo "") TAG=$(echo "$RELEASE_JSON" | grep '"tag_name"' | sed 's/.*"v\(.*\)",/\1/') if [ -z "$TAG" ]; then echo -e "${RED}Failed to fetch latest release info.${NC}" exit 1 fi echo "Latest version: v$TAG" TMPDIR=$(mktemp -d) cleanup() { rm -rf "$TMPDIR"; } trap cleanup EXIT # Try tarball first, then .deb TARBALL="vietc_${TAG}_linux_${ARCH}.tar.gz" TARBALL_URL="https://github.com/vndangkhoa/vietc/releases/download/v${TAG}/${TARBALL}" DEB="vietc_${TAG}-1_amd64.deb" DEB_URL="https://github.com/vndangkhoa/vietc/releases/download/v${TAG}/${DEB}" INSTALL_DIR="$TMPDIR/install" mkdir -p "$INSTALL_DIR" if curl -sSfL -o "$TMPDIR/$TARBALL" "$TARBALL_URL" 2>/dev/null; then echo "Downloading tarball..." tar -xzf "$TMPDIR/$TARBALL" -C "$INSTALL_DIR" BIN_DIR="$INSTALL_DIR/vietc_${TAG}_linux_${ARCH}/bin" PKG_DIR="$INSTALL_DIR/vietc_${TAG}_linux_${ARCH}" elif curl -sSfL -o "$TMPDIR/$DEB" "$DEB_URL" 2>/dev/null; then echo "Downloading .deb package..." if command -v dpkg-deb &>/dev/null; then dpkg-deb -x "$TMPDIR/$DEB" "$INSTALL_DIR" else ar x "$TMPDIR/$DEB" --output="$TMPDIR/deb" 2>/dev/null tar -xzf "$TMPDIR/deb/data.tar.gz" -C "$INSTALL_DIR" 2>/dev/null || \ tar -xJf "$TMPDIR/deb/data.tar.xz" -C "$INSTALL_DIR" 2>/dev/null || true fi BIN_DIR="$INSTALL_DIR/usr/bin" PKG_DIR="$INSTALL_DIR" else echo -e "${RED}No prebuilt binary found for v$TAG ($ARCH).${NC}" echo -e "${YELLOW}Visit https://github.com/vndangkhoa/vietc/releases${NC}" exit 1 fi # Kill old processes pkill -x vietc-tray 2>/dev/null || true pkill -x vietc-daemon 2>/dev/null || true pkill -x vietc 2>/dev/null || true # Install binaries echo "Installing to /usr/bin/..." cp "$BIN_DIR/vietc-daemon" /usr/bin/vietc-daemon cp "$BIN_DIR/vietc-cli" /usr/bin/vietc-cli cp "$BIN_DIR/vietc-uinputd" /usr/bin/vietc-uinputd cp "$BIN_DIR/vietc-tray" /usr/bin/vietc-tray [ -f "$BIN_DIR/vietc-xrecord" ] && cp "$BIN_DIR/vietc-xrecord" /usr/bin/vietc-xrecord chmod 755 /usr/bin/vietc-daemon /usr/bin/vietc-cli /usr/bin/vietc-uinputd /usr/bin/vietc-tray 2>/dev/null || true # Clean old /usr/local/bin/ binaries rm -f /usr/local/bin/vietc /usr/local/bin/vietc-daemon /usr/local/bin/vietc-cli \ /usr/local/bin/vietc-uinputd /usr/local/bin/vietc-tray /usr/local/bin/vietc-xrecord 2>/dev/null || true # Udev rules echo 'KERNEL=="uinput", GROUP="input", MODE="0660"' > /etc/udev/rules.d/99-vietc.rules udevadm control --reload-rules 2>/dev/null || true udevadm trigger 2>/dev/null || true # Icons if [ -d "$PKG_DIR/icons" ]; then mkdir -p /usr/share/icons/hicolor/256x256/apps cp "$PKG_DIR/icons"/*.svg /usr/share/icons/hicolor/256x256/apps/ 2>/dev/null || true elif [ -d "$INSTALL_DIR/usr/share/icons" ]; then cp -r "$INSTALL_DIR/usr/share/icons/"* /usr/share/icons/ 2>/dev/null || true fi # Desktop file if [ -f "$PKG_DIR/desktop/vietc.desktop" ]; then mkdir -p /usr/share/applications cp "$PKG_DIR/desktop/vietc.desktop" /usr/share/applications/ elif [ -f "$INSTALL_DIR/usr/share/applications/vietc.desktop" ]; then cp "$INSTALL_DIR/usr/share/applications/vietc.desktop" /usr/share/applications/ fi # XDG autostart mkdir -p /etc/xdg/autostart cat > /etc/xdg/autostart/vietc-tray.desktop << 'EOF' [Desktop Entry] Type=Application Name=Viet+ Tray Comment=Vietnamese Input Method Tray Exec=vietc-tray Icon=vietc Terminal=false Categories=Utility; StartupNotify=false NoDisplay=true EOF # Systemd user service mkdir -p /usr/lib/systemd/user cat > /usr/lib/systemd/user/vietc.service << 'EOF' [Unit] Description=Viet+ Vietnamese IME Tray PartOf=graphical-session.target [Service] Type=simple ExecStart=/usr/bin/vietc-tray Restart=on-failure RestartSec=5 [Install] WantedBy=default.target EOF # User setup INSTALLING_USER="${SUDO_USER:-$USER}" if [ -n "$INSTALLING_USER" ] && [ "$INSTALLING_USER" != "root" ]; then if command -v usermod &>/dev/null; then usermod -aG input "$INSTALLING_USER" 2>/dev/null || true elif command -v adduser &>/dev/null; then adduser "$INSTALLING_USER" input 2>/dev/null || true fi rm -f "$(getent passwd "$INSTALLING_USER" | cut -d: -f6)/.config/vietc/config.toml" 2>/dev/null || true fi # Config mkdir -p /etc/vietc if [ -f "$PKG_DIR/config/config.toml" ]; then cp "$PKG_DIR/config/config.toml" /etc/vietc/config.toml elif [ -f "$INSTALL_DIR/etc/vietc/config.toml" ]; then cp "$INSTALL_DIR/etc/vietc/config.toml" /etc/vietc/config.toml fi if [ ! -f /etc/vietc/config.toml ]; then cat > /etc/vietc/config.toml << 'EOF' input_method = "vni" toggle_key = "space" start_enabled = true grab = true [app_state] enabled = true english_apps = ["code", "vim"] vietnamese_apps = ["telegram", "discord", "firefox"] EOF fi echo -e "${GREEN}=== Done! ===${NC}" echo -e "${YELLOW}Log out and log back in, then run: vietc-tray${NC}"