Skip to content

Commit

Permalink
Element-desktop for Ghaf
Browse files Browse the repository at this point in the history
Add modified element-desktop icon to guivm and Element application to element appvm:
Element-desktop from nixpkgs does not work on Ghaf. Element-desktop pathced
so that application starts on guivm.

Element-web includes location sharing:
modifications so that GPS receiver can can be used for location sharing.
An additional element-gps application is added that allows using websockets
interface to receive GPS NMEA messages in Element-web implementation instead
of Google location API.

Signed-off-by: Timo Piiroinen <timo.piiroinen@unikie.com>

Element desktop for Ghaf

Patched the element-desktop Nix package to start using waypipe.
Added gpsd and element-gps services for element-vm if GPS transceiver is used.

Revert guivm.nix modifications

Remove the temporary modifications applied on last commit.

Signed-off-by: Timo Piiroinen <timo.piiroinen@unikie.com>

Reformat code using nix fmt

Applied nix fmt command to to pass the check .nix formatting test

Signed-off-by: Timo Piiroinen <timo.piiroinen@unikie.com>

Revert debug-tools.nix

Remove temporary changes from debug-tools.nix file.

Signed-off-by: Timo Piiroinen <timo.piiroinen@unikie.com>

Fix issue causing high cpu usage when gps transceiver is not connected

The gpspipe subprocess return code hangling added to read loop.
If gpsd daemon is not running the gpspipe will exit with faulcode.

Signed-off-by: Timo Piiroinen <timo.piiroinen@unikie.com>

Fixed the startup syntax after rebase to Ghaf/main

Old syntax fails so startup script aligned to new format.

Signed-off-by: Timo Piiroinen <timo.piiroinen@unikie.com>

Desktop icon update and copyright year update

Element logo update to custom and copyright text is modified to current year.
Remove redundancy from nix files as suggested in PR review.

Signed-off-by: Timo Piiroinen <timo.piiroinen@unikie.com>
  • Loading branch information
TPiUnikie authored and Mika Tammi committed Apr 21, 2024
1 parent 1aa92df commit aaf150e
Show file tree
Hide file tree
Showing 16 changed files with 636 additions and 0 deletions.
Binary file added assets/icons/png/element.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions modules/common/hardware/lenovo-x1/definitions/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ in {
SUBSYSTEM=="input", ATTRS{name}=="TPPS/2 Elan TrackPoint", GROUP="kvm"
# Lenovo X1 integrated webcam
KERNEL=="3-8", SUBSYSTEM=="usb", ATTR{busnum}=="3", ATTR{devnum}=="3", GROUP="kvm"
# External USB GPS receiver
SUBSYSTEM=="usb", ATTR{idVendor}=="067b", ATTR{idProduct}=="23a3", GROUP="kvm"
# Mouse and Touchpad
${lib.strings.concatStrings (mapMouseRules hwDefinition.mouse)}
${lib.strings.concatStrings (mapTouchpadRules hwDefinition.touchpad)}
Expand Down
3 changes: 3 additions & 0 deletions overlays/custom-packages/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
#
(final: prev: {
gala-app = final.callPackage ../../packages/gala {};
element-desktop = import ./element-desktop {inherit prev;};
element-gps = final.callPackage ../../packages/element-gps {};
element-web = final.callPackage ../../packages/element-web {};
systemd = import ./systemd {inherit final prev;};
waypipe = import ./waypipe {inherit final prev;};
weston = import ./weston {inherit final prev;};
Expand Down
9 changes: 9 additions & 0 deletions overlays/custom-packages/element-desktop/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
#
# This overlay customizes element-desktop
#
{prev}:
prev.element-desktop.overrideAttrs (_prevAttrs: {
patches = [./element-main.patch];
})
94 changes: 94 additions & 0 deletions overlays/custom-packages/element-desktop/element-main.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
diff --git a/src/electron-main.ts b/src/electron-main.ts
index b5d13ac..ffffb76 100644
--- a/src/electron-main.ts
+++ b/src/electron-main.ts
@@ -456,11 +456,10 @@ app.on("ready", async () => {
// https://www.electronjs.org/docs/faq#the-font-looks-blurry-what-is-this-and-what-can-i-do
backgroundColor: "#fff",

- titleBarStyle: process.platform === "darwin" ? "hidden" : "default",
trafficLightPosition: { x: 9, y: 8 },

icon: global.trayConfig.icon_path,
- show: false,
+ show: true,
autoHideMenuBar: global.store.get("autoHideMenuBar", true),

x: mainWindowState.x,
@@ -475,67 +474,39 @@ app.on("ready", async () => {
webgl: true,
},
});
- global.mainWindow.loadURL("vector://vector/webapp/");
-
- if (process.platform === "darwin") {
- setupMacosTitleBar(global.mainWindow);
- }
+

// Handle spellchecker
// For some reason spellCheckerEnabled isn't persisted, so we have to use the store here
global.mainWindow.webContents.session.setSpellCheckerEnabled(global.store.get("spellCheckerEnabled", true));

- // Create trayIcon icon
- if (global.store.get("minimizeToTray", true)) tray.create(global.trayConfig);

- global.mainWindow.once("ready-to-show", () => {
+ global.mainWindow.webContents.once('did-finish-load',function(){
if (!global.mainWindow) return;
mainWindowState.manage(global.mainWindow);

if (!argv["hidden"]) {
global.mainWindow.show();
+ global.mainWindow.restore();
++ global.mainWindow.focus();
+
} else {
// hide here explicitly because window manage above sometimes shows it
global.mainWindow.hide();
}
});

- global.mainWindow.webContents.on("before-input-event", warnBeforeExit);
+ global.mainWindow.loadURL("vector://vector/webapp/");

global.mainWindow.on("closed", () => {
global.mainWindow = null;
});
+
global.mainWindow.on("close", async (e) => {
- // If we are not quitting and have a tray icon then minimize to tray
- if (!global.appQuitting && (tray.hasTray() || process.platform === "darwin")) {
- // On Mac, closing the window just hides it
- // (this is generally how single-window Mac apps
- // behave, eg. Mail.app)
- e.preventDefault();
-
- if (global.mainWindow?.isFullScreen()) {
- global.mainWindow.once("leave-full-screen", () => global.mainWindow?.hide());
-
- global.mainWindow.setFullScreen(false);
- } else {
- global.mainWindow?.hide();
- }
-
- return false;
- }
+ // Close event handler
+ // Default behaviour is minimize to tray, that feature is removed since there is no tray support on Ghaf
});

- if (process.platform === "win32") {
- // Handle forward/backward mouse buttons in Windows
- global.mainWindow.on("app-command", (e, cmd) => {
- if (cmd === "browser-backward" && global.mainWindow?.webContents.canGoBack()) {
- global.mainWindow.webContents.goBack();
- } else if (cmd === "browser-forward" && global.mainWindow?.webContents.canGoForward()) {
- global.mainWindow.webContents.goForward();
- }
- });
- }
-
webContentsHandler(global.mainWindow.webContents);

global.appLocalization = new AppLocalization({
5 changes: 5 additions & 0 deletions overlays/custom-packages/element-gps/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
(final: _prev: {
element-gps = final.callPackage ../../../packages/element-gps {};
})
5 changes: 5 additions & 0 deletions overlays/custom-packages/element-web/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
(final: _prev: {
element-web = final.callPackage ../../../packages/element-web {};
})
12 changes: 12 additions & 0 deletions packages/element-gps/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
{python3Packages}:
with python3Packages;
buildPythonApplication {
pname = "gpswebsock";
version = "1.0";

propagatedBuildInputs = [websockets];

src = ./.;
}
121 changes: 121 additions & 0 deletions packages/element-gps/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#!/usr/bin/env python

# Copyright 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0

import asyncio
import functools
import json
import signal
import threading

import websockets


class GpsProcessState:
def __init__(self):
self._gps_data = str()
self.data_lock = asyncio.Lock()
self.condition = asyncio.Condition()
self.abort_websockets = False
self.terminate = asyncio.Event()
self.stop_event = threading.Event()
self.stop_wait_asyncio = asyncio.get_event_loop().run_in_executor(
None, self.stop_event.wait
)

def get_data(self):
return self._gps_data

def set_data(self, value):
self._gps_data = value

def del_data(self):
del self._gps_data

message = property(get_data, set_data, del_data)


async def read_continuous_gps(data):
process = await asyncio.create_subprocess_exec(
"gpspipe", "-w", stdin=asyncio.subprocess.PIPE, stdout=asyncio.subprocess.PIPE
)
print("GPS reader process PID:", {process.pid}, "starting...")

while not data.terminate.is_set():
if process.returncode is not None:
print("gpspipe process has exited")
break

line = await process.stdout.readline()
line = line.decode()

if len(line) != 0:
reply_json = json.loads(line)
if reply_json["class"] == "TPV":
async with data.data_lock:
data.message = line
async with data.condition:
data.condition.notify_all()

print("Closing service...")
# Notify all websockets to quit
async with data.condition:
data.abort_websockets = True
data.condition.notify_all()
await asyncio.sleep(2)
data.stop_event.set()


async def handler(websocket, path, gps_state):
print("New connection received")
while not gps_state.abort_websockets:
async with gps_state.condition:
await gps_state.condition.wait()
if gps_state.abort_websockets:
break
async with gps_state.data_lock:
output = gps_state.message
try:
await websocket.send(output)
except Exception:
print("Client disconnected.")
break
print("Closing websocket...")


async def wait_connection(gps_state):
print("Websocket listener on localhost:8000.")
async with websockets.serve(
functools.partial(handler, gps_state=gps_state), "localhost", 8000
):
await gps_state.stop_wait_asyncio
print("Closing websocket listener.")


def signal_handler(signum, frame, state_object):
# ignore additional signals
signal.signal(signum, signal.SIG_IGN)
state_object.terminate.set()


async def main():
gps_state = GpsProcessState()
# The stop condition is set when receiving SIGTERM or SIGINT.
signal.signal(
signal.SIGINT, functools.partial(signal_handler, state_object=gps_state)
)
signal.signal(
signal.SIGTERM, functools.partial(signal_handler, state_object=gps_state)
)
await asyncio.gather(read_continuous_gps(gps_state), wait_connection(gps_state))


if __name__ == "__main__":
loop = asyncio.get_event_loop()
stop = loop.create_future()
loop.add_signal_handler(signal.SIGTERM, stop.set_result, None)
try:
loop.run_until_complete(main())
finally:
loop.close()
15 changes: 15 additions & 0 deletions packages/element-gps/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env python

# Copyright 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0

from setuptools import find_packages, setup

setup(
name="gpswebsock",
version="1.0",
# Modules to import from other scripts:
packages=find_packages(),
# Executables
scripts=["main.py"],
)
89 changes: 89 additions & 0 deletions packages/element-web/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Copyright 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
{
lib,
stdenv,
fetchFromGitHub,
fetchYarnDeps,
jq,
yarn,
fixup_yarn_lock,
nodejs,
jitsi-meet,
}: let
pinData = import ./pin.nix;
inherit (pinData.hashes) webSrcHash webYarnHash;
noPhoningHome = {
disable_guests = true; # disable automatic guest account registration at matrix.org
};
in
stdenv.mkDerivation (finalAttrs:
builtins.removeAttrs pinData ["hashes"]
// {
pname = "element-web";

src = fetchFromGitHub {
owner = "vector-im";
repo = finalAttrs.pname;
rev = "v${finalAttrs.version}";
hash = webSrcHash;
};

offlineCache = fetchYarnDeps {
yarnLock = finalAttrs.src + "/yarn.lock";
sha256 = webYarnHash;
};

nativeBuildInputs = [yarn fixup_yarn_lock jq nodejs];

configurePhase = ''
runHook preConfigure
export HOME=$PWD/tmp
# with the update of openssl3, some key ciphers are not supported anymore
# this flag will allow those codecs again as a workaround
# see https://medium.com/the-node-js-collection/node-js-17-is-here-8dba1e14e382#5f07
# and https://github.com/vector-im/element-web/issues/21043
export NODE_OPTIONS=--openssl-legacy-provider
mkdir -p $HOME
fixup_yarn_lock yarn.lock
yarn config --offline set yarn-offline-mirror $offlineCache
yarn install --offline --frozen-lockfile --ignore-platform --ignore-scripts --no-progress --non-interactive
patch -p1 < ${./matrix-react-sdk.patch}
patchShebangs node_modules
runHook postConfigure
'';

buildPhase = ''
runHook preBuild
export VERSION=${finalAttrs.version}
yarn build:res --offline
yarn build:module_system --offline
yarn build:bundle --offline
runHook postBuild
'';

installPhase = ''
runHook preInstall
cp -R webapp $out
cp ${jitsi-meet}/libs/external_api.min.js $out/jitsi_external_api.min.js
echo "${finalAttrs.version}" > "$out/version"
jq -s '.[0] * $conf' "config.sample.json" --argjson "conf" '${builtins.toJSON noPhoningHome}' > "$out/config.json"
runHook postInstall
'';

meta = {
description = "A glossy Matrix collaboration client for the web";
homepage = "https://element.io/";
changelog = "https://github.com/vector-im/element-web/blob/v${finalAttrs.version}/CHANGELOG.md";
maintainers = lib.teams.matrix.members;
license = lib.licenses.asl20;
platforms = lib.platforms.all;
};
})
Loading

0 comments on commit aaf150e

Please sign in to comment.