- `,
+ `,
+ ];
- is: 'servers-view',
+ @property({type: Function}) localize: Localizer = msg => msg;
+ @property({type: Boolean}) shouldShowAccessKeyWikiLink = false;
+ @property({type: Array}) servers: ServerListItem[] = [];
- properties: {
- localize: Function,
- useAltAccessMessage: Boolean,
- servers: Array,
- shouldShowZeroState: {
- type: Boolean,
- computed: '_computeShouldShowZeroState(servers)',
- },
- },
+ get shouldShowZeroState() {
+ return this.servers ? this.servers.length === 0 : false;
+ }
- _computeShouldShowZeroState(servers: ServerListItem[]) {
- return servers ? servers.length === 0 : false;
- },
+ private requestPromptAddServer() {
+ this.dispatchEvent(new CustomEvent('add-server', {bubbles: true, composed: true}));
+ }
- _requestPromptAddServer() {
- this.fire('PromptAddServerRequested', {});
- },
-});
+ private get zeroStateContent(): DirectiveResult {
+ let msg;
+ if (this.shouldShowAccessKeyWikiLink) {
+ msg = this.localize(
+ 'server-create-your-own-zero-state-access',
+ 'breakLine', ' ',
+ 'openLink', '',
+ 'openLink2', '',
+ 'closeLink', '');
+ } else {
+ msg = this.localize(
+ 'server-create-your-own-zero-state',
+ 'breakLine', ' ',
+ 'openLink', '',
+ 'closeLink', '');
+ }
+ return unsafeHTML(msg);
+ }
+
+ render() {
+ if (this.shouldShowZeroState) {
+ return html`
+
+
+
+
+
+
+ `;
+ } else {
+ return html`
+
+ `;
+ }
+ }
+}
diff --git a/client/tools/find_tap_name/bin/386/find_tap_name.exe b/client/tools/find_tap_name/bin/386/find_tap_name.exe
deleted file mode 100755
index 3845c099aa..0000000000
Binary files a/client/tools/find_tap_name/bin/386/find_tap_name.exe and /dev/null differ
diff --git a/client/tools/find_tap_name/bin/amd64/find_tap_name.exe b/client/tools/find_tap_name/bin/amd64/find_tap_name.exe
deleted file mode 100755
index 3845c099aa..0000000000
Binary files a/client/tools/find_tap_name/bin/amd64/find_tap_name.exe and /dev/null differ
diff --git a/client/tools/find_tap_name/build.action.sh b/client/tools/find_tap_name/build.action.sh
deleted file mode 100755
index fb9b6b107d..0000000000
--- a/client/tools/find_tap_name/build.action.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2019 The Outline Authors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-set -eux
-
-pushd "$ROOT_DIR/tools/find_tap_name/" > /dev/null
-GOOS=windows; GOARCH=386; go build -o bin/386/
-GOOS=windows; GOARCH=amd64; go build -o bin/amd64/
diff --git a/client/tools/find_tap_name/main.go b/client/tools/find_tap_name/main.go
deleted file mode 100755
index 494d820328..0000000000
--- a/client/tools/find_tap_name/main.go
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2019 The Outline Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- "encoding/binary"
- "flag"
- "fmt"
- "io/ioutil"
- "log"
- "sort"
- "strings"
-
- "golang.org/x/sys/windows/registry"
-)
-
-const (
- // netAdaptersKeyPath is the registry location of the system's network adapters.
- netAdaptersKeyPath = `SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}`
- // netConfigKeyPath is the registry location of the network adapters network configuration.
- netConfigKeyPath = `SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}`
-)
-
-type networkAdapter struct {
- name string
- installTimestamp uint64
-}
-
-// getAdapterNameAndInstallTimestamp returns the name and install timestamp of a network adapter with
-// registry location `adapterKeyPath`. Returns a non-nil error on failure, or if the adapter's
-// hardware component ID does not match `componentID`.
-func getAdapterNameAndInstallTimestamp(adapterKeyPath, componentID string) (name string, installTimestamp uint64, err error) {
- adapterKey, err := registry.OpenKey(registry.LOCAL_MACHINE, adapterKeyPath, registry.READ)
- if err != nil {
- log.Println("Failed to open adapter key:", err)
- return
- }
- defer adapterKey.Close()
-
- adapterComponentID, _, err := adapterKey.GetStringValue("ComponentId")
- if err != nil {
- log.Println("Failed to read adapter component ID:", err)
- return
- }
- if adapterComponentID != componentID {
- err = fmt.Errorf("Network adapter component ID does not match %v", componentID)
- return
- }
-
- installTimestampBytes, _, err := adapterKey.GetBinaryValue("InstallTimeStamp")
- if err != nil {
- log.Println("Failed to read adapter install timestamp:", err)
- return
- }
- // Although Windows is little endian, we have observed that network adapters' install timestamps
- // are encoded as big endian in the registry.
- installTimestamp = binary.BigEndian.Uint64(installTimestampBytes)
-
- netConfigID, _, err := adapterKey.GetStringValue("NetCfgInstanceId")
- if err != nil {
- log.Println("Failed to read network configuration ID:", err)
- return
- }
- adapterConfigKeyPath := fmt.Sprintf(`%s\%s\Connection`, netConfigKeyPath, netConfigID)
- adapterConfigKey, err := registry.OpenKey(registry.LOCAL_MACHINE, adapterConfigKeyPath, registry.READ)
- if err != nil {
- log.Println("Failed to open network configuration key:", err)
- return
- }
- defer adapterConfigKey.Close()
-
- name, _, err = adapterConfigKey.GetStringValue("Name")
- if err != nil {
- log.Println("Failed to read adapter name:", err)
- return
- }
- return
-}
-
-// findNetworkAdapters searches the Windows registry for network adapters with `componentID`.
-// Returns an empty slice and an error if no network adapters are found.
-func findNetworkAdapters(componentID string, ignoredNames map[string]bool) ([]networkAdapter, error) {
- netAdapters := make([]networkAdapter, 0)
- netAdaptersKey, err := registry.OpenKey(registry.LOCAL_MACHINE, netAdaptersKeyPath, registry.READ)
- if err != nil {
- return netAdapters, fmt.Errorf("Failed to open the network adapter registry, %w", err)
- }
- defer netAdaptersKey.Close()
-
- // List all network adapters.
- adapterKeys, err := netAdaptersKey.ReadSubKeyNames(-1)
- if err != nil {
- return netAdapters, err
- }
-
- for _, k := range adapterKeys {
- adapterKeyPath := fmt.Sprintf(`%s\%s`, netAdaptersKeyPath, k)
- adapterName, adapterInstallTimestamp, err := getAdapterNameAndInstallTimestamp(adapterKeyPath, componentID)
- if err != nil {
- continue
- }
- if ignoredNames[adapterName] {
- continue
- }
- netAdapters = append(netAdapters, networkAdapter{name: adapterName, installTimestamp: adapterInstallTimestamp})
- }
-
- if len(netAdapters) == 0 {
- err = fmt.Errorf("Could not find network adapters with the specified component ID")
- }
- return netAdapters, err
-}
-
-// readIgnoredNetworkAdapterNames reads a comma-separated list of network interface names at
-// `filename` and returns a map keyed by name.
-func readIgnoredNetworkAdapterNames(filename string) map[string]bool {
- ignoredNames := make(map[string]bool)
- if filename == "" {
- return ignoredNames
- }
-
- names, err := ioutil.ReadFile(filename)
- if err != nil {
- log.Println("Failed to read ignored network adapters file:", err)
- return ignoredNames
- }
-
- for _, name := range strings.Split(string(names), ",") {
- if len(name) == 0 {
- continue;
- }
- ignoredNames[name] = true
- }
- return ignoredNames
-}
-
-func main() {
- componentID := flag.String("component-id", "tap0901", "Hardware component ID of the network adapter")
- ignoredNamesPath := flag.String("ignored-names", "", "Path to a comma-separated list of network adapter names to exclude from the search")
- flag.Parse()
-
- // Remove timestamps, output to stderr by default.
- log.SetFlags(0)
-
- ignoredNames := readIgnoredNetworkAdapterNames(*ignoredNamesPath)
- log.Println("Ignoring:", ignoredNames)
-
- netAdapters, err := findNetworkAdapters(*componentID, ignoredNames)
- if err != nil {
- log.Fatalf(err.Error())
- }
- // Sort the network adapters by most recent install timestamp.
- sort.Slice(netAdapters, func(i, j int) bool {
- return netAdapters[i].installTimestamp > netAdapters[j].installTimestamp
- })
- log.Println("Network adapters", netAdapters)
-
- // Output the most recently installed adapter name to stdout.
- fmt.Print(netAdapters[0].name)
-}
diff --git a/package-lock.json b/package-lock.json
index e4abd813ba..d5e246cd3b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -121,8 +121,7 @@
"karma-webpack": "^5.0.0",
"minimist": "^1.2.6",
"node-fetch": "^3.3.0",
- "node-gyp": "^10.1.0",
- "outline-i18n": "Jigsaw-Code/outline-i18n#v0.0.7",
+ "node-gyp": "^10.0.1",
"postcss": "^7.0.39",
"postcss-rtl": "^1.7.3",
"prettier": "^2.8.0",
diff --git a/src/electron/README.md b/src/electron/README.md
index 331658da54..d737bdfb95 100644
--- a/src/electron/README.md
+++ b/src/electron/README.md
@@ -1,21 +1,7 @@
-## Electron Development Instructions
+# Electron Development Instructions
Unlike the Android and Apple clients, the Windows and Linux clients use the Electron framework, rather than Cordova.
-You will need [Docker](https://www.docker.com/) installed to build the Electron clients.
-
-> If you can't use Docker, you can use [podman](https://podman.io) as substitute by running the following (for macOS):
-
-```sh
-brew install podman
-podman machine init
-sudo ln -s $(which podman) /usr/local/bin/docker
-sudo /opt/homebrew/Cellar/podman//bin/podman-mac-helper install
-podman machine start
-```
-
-> You may run into the error: `/var/folders//xgo-cache: no such file or directory`. If so, simply create that directory with `mkdir -p /var/folders//xgo-cache` and try again.
-
To build the Electron clients, run (it will also package an installer executable into `build/dist`):
```sh
@@ -28,8 +14,21 @@ To run the Electron clients, run:
npm run action electron/start [windows|linux]
```
-### Windows
+## Cross-Compiling
+
+To build the app for a platform target on a different host target, you will need a cross-compiler. We use [zig to cross-compile with cgo](https://dev.to/kristoff/zig-makes-go-cross-compilation-just-work-29ho).
+
+[Install zig](https://ziglang.org/learn/getting-started/#installing-zig) and make sure it's in the PATH.
+
+You can download the binary tarball, or [use a package manager](https://github.com/ziglang/zig/wiki/Install-Zig-from-a-Package-Manager), like Homebrew:
+
+```sh
+brew install zig
+```
+
+## Release
To build the _release_ version of Windows installer, you'll also need:
- [Java 8+ Runtime](https://www.java.com/en/download/). This is required for the cross-platform Windows executable signing tool [Jsign](https://ebourg.github.io/jsign/). If you don't need to sign the executables, feel free to skip this.
+
diff --git a/src/electron/electron-builder.json b/src/electron/electron-builder.json
index 76ade7c8e5..c182416a39 100644
--- a/src/electron/electron-builder.json
+++ b/src/electron/electron-builder.json
@@ -1,5 +1,5 @@
{
- "files": ["build/electron", "www", "resources/tray", "!node_modules/electron"],
+ "files": ["build/electron", "www", "client/resources/tray", "!node_modules/electron"],
"asarUnpack": ["output", "tools"],
"artifactName": "Outline-Client.${ext}",
"directories": {
diff --git a/src/electron/find_tap_device_name.bat b/src/electron/find_tap_device_name.bat
index 52b41c381f..d5b81d08d7 100755
--- a/src/electron/find_tap_device_name.bat
+++ b/src/electron/find_tap_device_name.bat
@@ -15,7 +15,13 @@
:: Queries the registry in order to retrieve the most recently installed TAP network adapter's name.
:: Accepts a single argument, the name of an environment variable to store the adapter's name.
:: Exits with a non-zero exit code on failure.
-:: Usage example: find_tap_name.bat TAP_NAME
+:: Usage example: find_tap_device_name.bat TAP_NAME
+
+:: Some history:
+:: We used to use a Go binary for this to improve the name detection:
+:: https://github.com/Jigsaw-Code/outline-apps/pull/711
+:: It was later replaced by this script "following reports that the Go binaries fail to run on some environments":
+:: https://github.com/Jigsaw-Code/outline-apps/pull/756
@echo off
:: See https://ss64.com/nt/delayedexpansion.html
diff --git a/src/electron/index.ts b/src/electron/index.ts
index a3749bb403..70c06f2f44 100644
--- a/src/electron/index.ts
+++ b/src/electron/index.ts
@@ -223,7 +223,7 @@ function updateTray(status: TunnelStatus) {
}
function createTrayIconImage(imageName: string) {
- const image = nativeImage.createFromPath(path.join(app.getAppPath(), 'resources', 'tray', imageName));
+ const image = nativeImage.createFromPath(path.join(app.getAppPath(), 'client', 'resources', 'tray', imageName));
if (image.isEmpty()) {
throw new Error(`cannot find ${imageName} tray icon image`);
}