Skip to content

Commit a7f9b6e

Browse files
committed
feat: override app path
1 parent 6ef9fa9 commit a7f9b6e

5 files changed

Lines changed: 55 additions & 22 deletions

File tree

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,18 @@ Install the official [Slack app](https://slack.com/downloads/mac) (not the App S
3030
curl -fsSL https://raw.githubusercontent.com/3kh0/slick/main/install.sh | bash
3131
```
3232

33+
If Slack is installed somewhere else, pass its app bundle with `--slack-app`:
34+
35+
```bash
36+
./install.sh --slack-app "$HOME/Documents/Apps/Slack.app"
37+
```
38+
39+
When using the remote installer, pass the option to `bash` like this:
40+
41+
```bash
42+
curl -fsSL https://raw.githubusercontent.com/3kh0/slick/main/install.sh | bash -s -- --slack-app "$HOME/Documents/Apps/Slack.app"
43+
```
44+
3345
If you prefer doing it by hand, grab the latest prebuilt app from the [releases page](https://github.com/3kh0/slick/releases/latest) and pick the build for your Mac (check > About This Mac > Chip if unsure):
3446

3547
- `Slick-build-N-mac-arm64`**Apple Silicon** (if there is a M in the name)

install.sh

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,29 @@ exit(LSSetDefaultHandlerForURLScheme("slack" as NSString as CFString, id as NSSt
4343
EOF
4444
}
4545

46-
if [ "${1:-}" = "--restore-handler" ]; then
47-
handler com.tinyspeck.slackmacgap && echo "slack:// now opens the official Slack again." || die "could not restore handler"
48-
exit 0
49-
fi
46+
while [ "$#" -gt 0 ]; do
47+
case "$1" in
48+
--slack-app)
49+
[ "$#" -ge 2 ] || die "--slack-app needs a path"
50+
SLACK="${2%/}"
51+
shift 2
52+
;;
53+
--restore-handler)
54+
handler com.tinyspeck.slackmacgap && echo "slack:// now opens the official Slack again." || die "could not restore handler"
55+
exit 0
56+
;;
57+
*) die "unknown option: $1" ;;
58+
esac
59+
done
5060

5161
step "Checking prerequisites"
5262
[ "$(uname -s)" = "Darwin" ] || die "Slick only supports macOS :("
5363
[ -f "$SLACK/Contents/Resources/app.asar" ] \
5464
|| die "Slack not found at $SLACK, please install it from slack.com first."
65+
SLACK="$(cd "$(dirname "$SLACK")" && pwd)/$(basename "$SLACK")"
66+
SLACK_CONFIG="$HOME/Library/Application Support/Slick/slick/slack-app-path"
67+
mkdir -p "$(dirname "$SLACK_CONFIG")"
68+
printf '%s\n' "$SLACK" > "$SLACK_CONFIG"
5569

5670
if [ -f "$ROOT/scripts/byoe/build-handoff-app.js" ]; then
5771
node -e 'process.exit(parseInt(process.versions.node, 10) >= 18 ? 0 : 1)' 2>/dev/null \
@@ -99,7 +113,7 @@ if [ -f "$ROOT/scripts/byoe/build-handoff-app.js" ]; then
99113
step "Building $APP (Build $BUILD)"
100114
node "$ROOT/scripts/byoe/build-handoff-app.js" --target "$APP" \
101115
--profile "$HOME/Library/Application Support/Slack" \
102-
--app-version "$VERSION" --build-number "$BUILD" --allow-non-tmp --force >/dev/null
116+
--slack-app "$SLACK" --app-version "$VERSION" --build-number "$BUILD" --allow-non-tmp --force >/dev/null
103117

104118
step "Installing icon"
105119
"$ROOT/scripts/byoe/set-icon.sh" 2>&1 | while IFS= read -r line; do printf ' %s\n' "$line"; done

scripts/byoe/build-handoff-app.js

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,13 @@ const { spawnSync } = require('child_process');
77

88
const ROOT = path.resolve(__dirname, '..', '..');
99
const DEFAULT_SOURCE_APP = path.join(ROOT, 'byoe/node_modules/electron/dist/Electron.app');
10-
const SLACK_RESOURCES = '/Applications/Slack.app/Contents/Resources';
11-
const SLACK_ASAR = path.join(SLACK_RESOURCES, 'app.asar');
1210
const ENTITLEMENTS = path.join(ROOT, 'scripts/release/entitlements.plist');
1311
const DEFAULTS = {
1412
target: '/tmp/slick/Slick.app',
1513
profile: '/tmp/slick/profile',
1614
appVersion: '1.0.0',
1715
buildNumber: '0',
16+
slackApp: '/Applications/Slack.app',
1817
sourceApp: process.env.SLICK_SOURCE_APP || DEFAULT_SOURCE_APP,
1918
force: false,
2019
allowNonTmp: false,
@@ -24,13 +23,15 @@ function usage() {
2423
console.error(`Usage:
2524
node scripts/byoe/build-handoff-app.js [--target <app>] [--profile <dir>] [--app-version <x.y.z>]
2625
[--build-number <n>]
26+
[--slack-app <Slack.app>]
2727
[--source-app <Electron.app>] [--force] [--allow-non-tmp]
2828
2929
Defaults:
3030
--target ${DEFAULTS.target}
3131
--profile ${DEFAULTS.profile}
3232
--app-version ${DEFAULTS.appVersion}
3333
--build-number ${DEFAULTS.buildNumber}
34+
--slack-app ${DEFAULTS.slackApp}
3435
--source-app ${DEFAULTS.sourceApp}`);
3536
process.exit(2);
3637
}
@@ -42,6 +43,7 @@ function parseArgs(argv) {
4243
else if (argv[i] === '--profile') o.profile = argv[++i] || usage();
4344
else if (argv[i] === '--app-version') o.appVersion = argv[++i] || usage();
4445
else if (argv[i] === '--build-number') o.buildNumber = argv[++i] || usage();
46+
else if (argv[i] === '--slack-app') o.slackApp = argv[++i] || usage();
4547
else if (argv[i] === '--source-app') o.sourceApp = argv[++i] || usage();
4648
else if (argv[i] === '--force') o.force = true;
4749
else if (argv[i] === '--allow-non-tmp') o.allowNonTmp = true;
@@ -179,17 +181,23 @@ const { app, dialog, shell, Menu, MenuItem } = require('electron');
179181
const SLICK_ROOT = path.join(process.resourcesPath, 'slick');
180182
const PROFILE = process.env.SLICK_HANDOFF_PROFILE || path.join(app.getPath('appData'), 'Slick');
181183
const DEFAULT_THEME = ${JSON.stringify(defaultTheme)};
182-
const SLACK_RESOURCES = ${JSON.stringify(SLACK_RESOURCES)};
183-
const SLACK_ASAR = ${JSON.stringify(SLACK_ASAR)};
184+
const DEFAULT_SLACK_APP = ${JSON.stringify(path.resolve(opts.slackApp))};
185+
const SLACK_PATH_CONFIG = path.join(PROFILE, 'slick', 'slack-app-path');
186+
let SLACK_APP = DEFAULT_SLACK_APP;
187+
try {
188+
SLACK_APP = fs.readFileSync(SLACK_PATH_CONFIG, 'utf8').trim() || DEFAULT_SLACK_APP;
189+
} catch {}
190+
const SLACK_RESOURCES = path.join(SLACK_APP, 'Contents', 'Resources');
191+
const SLACK_ASAR = path.join(SLACK_RESOURCES, 'app.asar');
184192
const SLICK_VERSION = ${JSON.stringify(opts.appVersion)};
185193
const SLICK_BUILD = parseInt(${JSON.stringify(opts.buildNumber)}, 10) || 0;
186194
const updater = require(path.join(SLICK_ROOT, 'scripts/byoe/updater.js')).create({ version: SLICK_VERSION, build: SLICK_BUILD, profile: PROFILE });
187195
const RELEASES_URL = updater.RELEASES_URL;
188-
const slackUpdater = require(path.join(SLICK_ROOT, 'scripts/byoe/slack-updater.js')).create({ version: SLICK_VERSION, profile: PROFILE });
196+
const slackUpdater = require(path.join(SLICK_ROOT, 'scripts/byoe/slack-updater.js')).create({ version: SLICK_VERSION, profile: PROFILE, slackApp: SLACK_APP });
189197
190198
function slackElectronMajor() {
191199
try {
192-
const plist = '/Applications/Slack.app/Contents/Frameworks/Electron Framework.framework/Resources/Info.plist';
200+
const plist = path.join(SLACK_APP, 'Contents/Frameworks/Electron Framework.framework/Resources/Info.plist');
193201
const raw = require('child_process').execFileSync(
194202
'/usr/bin/plutil', ['-extract', 'CFBundleVersion', 'raw', '-o', '-', plist], { encoding: 'utf8' },
195203
);
@@ -214,7 +222,7 @@ function handlePreflight(problem) {
214222
type: 'error',
215223
title: 'Slick',
216224
message: 'Slack is not installed',
217-
detail: 'Slick needs the official Slack app at /Applications/Slack.app. Install it from slack.com, then open Slick again.',
225+
detail: 'Slick needs the official Slack app at ' + SLACK_APP + '. Install it there or reinstall Slick with --slack-app, then open Slick again.',
218226
buttons: ['Quit'],
219227
});
220228
return false;
@@ -359,6 +367,7 @@ try {
359367
360368
function boot() {
361369
app.setPath('userData', PROFILE);
370+
process.env.SLICK_SLACK_APP = SLACK_APP;
362371
installPatch();
363372
seedSettings();
364373
updater.scheduleUpdateChecks();

scripts/byoe/inject.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ app.on('session-created', ap);
388388

389389
function installNotificationSounds() {
390390
if (process.platform !== 'darwin') return;
391-
const R = '/Applications/Slack.app/Contents/Resources';
391+
const R = path.join(process.env.SLICK_SLACK_APP || '/Applications/Slack.app', 'Contents', 'Resources');
392392
const s = path.join(app.getPath('home'), 'Library', 'Sounds');
393393
let names;
394394
try {

scripts/byoe/slack-updater.js

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ const https = require('https');
2626
const { execFile, execFileSync } = require('child_process');
2727

2828
const MAC = process.platform === 'darwin';
29-
const SLACK_APP = '/Applications/Slack.app';
30-
const SLACK_INFO_PLIST = path.join(SLACK_APP, 'Contents/Info.plist');
3129
const FRAMEWORK_PLIST_REL = 'Contents/Frameworks/Electron Framework.framework/Resources/Info.plist';
3230
const SLACK_BUNDLE_ID = 'com.tinyspeck.slackmacgap';
3331
const LATEST_REDIRECT = 'https://slack.com/ssb/download-osx-universal';
@@ -61,8 +59,6 @@ function plistValue(plist, key) {
6159
}
6260
const electronMajorOf = (app) => parseInt(plistValue(path.join(app, FRAMEWORK_PLIST_REL), 'CFBundleVersion'), 10) || 0;
6361
const bundleIdOf = (app) => plistValue(path.join(app, 'Contents/Info.plist'), 'CFBundleIdentifier');
64-
const installedVersion = () => plistValue(SLACK_INFO_PLIST, 'CFBundleShortVersionString');
65-
6662
// Move a bundle dir onto another path: cheap rename within a volume, ditto copy across.
6763
function moveDir(from, to) {
6864
try {
@@ -72,7 +68,9 @@ function moveDir(from, to) {
7268
}
7369
}
7470

75-
function create({ profile, version }) {
71+
function create({ profile, version, slackApp = '/Applications/Slack.app' }) {
72+
const slackInfoPlist = path.join(slackApp, 'Contents/Info.plist');
73+
const installedVersion = () => plistValue(slackInfoPlist, 'CFBundleShortVersionString');
7674
if (!MAC) {
7775
const noop = () => {};
7876
return {
@@ -168,17 +166,17 @@ function create({ profile, version }) {
168166
clearStaging()
169167
);
170168

171-
const backup = `${SLACK_APP}.slick-old`;
169+
const backup = `${slackApp}.slick-old`;
172170
try {
173171
fs.rmSync(backup, { recursive: true, force: true });
174-
if (fs.existsSync(SLACK_APP)) fs.renameSync(SLACK_APP, backup);
175-
moveDir(stagedApp, SLACK_APP);
172+
if (fs.existsSync(slackApp)) fs.renameSync(slackApp, backup);
173+
moveDir(stagedApp, slackApp);
176174
fs.rmSync(backup, { recursive: true, force: true });
177175
log(`installed Slack ${marker.version}`);
178176
} catch (e) {
179177
// Restore whatever we moved so the user is never left without Slack.
180178
try {
181-
if (!fs.existsSync(SLACK_APP) && fs.existsSync(backup)) fs.renameSync(backup, SLACK_APP);
179+
if (!fs.existsSync(slackApp) && fs.existsSync(backup)) fs.renameSync(backup, slackApp);
182180
} catch {}
183181
log(`failed to install staged Slack: ${msg(e)}`);
184182
} finally {

0 commit comments

Comments
 (0)