Skip to content

Commit

Permalink
feat(api/path): introduce well known path constants
Browse files Browse the repository at this point in the history
  • Loading branch information
jwerle committed Nov 8, 2023
1 parent f0fd30b commit 5ef69b3
Show file tree
Hide file tree
Showing 6 changed files with 295 additions and 7 deletions.
59 changes: 56 additions & 3 deletions api/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1177,17 +1177,64 @@ declare module "socket:path/posix" {

export { win32, Path };
}
declare module "socket:path/well-known" {
/**
* Well known path to the user's "Downloads" folder.
* @type {?string}
*/
export const DOWNLOADS: string | null;
/**
* Well known path to the user's "Documents" folder.
* @type {?string}
*/
export const DOCUMENTS: string | null;
/**
* Well known path to the user's "Pictures" folder.
* @type {?string}
*/
export const PICTURES: string | null;
/**
* Well known path to the user's "Desktop" folder.
* @type {?string}
*/
export const DESKTOP: string | null;
/**
* Well known path to the user's "Videos" folder.
* @type {?string}
*/
export const VIDEOS: string | null;
/**
* Well known path to the user's "Music" folder.
* @type {?string}
*/
export const MUSIC: string | null;
namespace _default {
export { DOWNLOADS };
export { DOCUMENTS };
export { PICTURES };
export { DESKTOP };
export { VIDEOS };
export { MUSIC };
}
export default _default;
}
declare module "socket:path/index" {
export * as _default from "socket:path/index";

import * as posix from "socket:path/posix";
import * as win32 from "socket:path/win32";
import { Path } from "socket:path/path";
export { posix, win32, Path };
import { DOWNLOADS } from "socket:path/well-known";
import { DOCUMENTS } from "socket:path/well-known";
import { PICTURES } from "socket:path/well-known";
import { DESKTOP } from "socket:path/well-known";
import { VIDEOS } from "socket:path/well-known";
import { MUSIC } from "socket:path/well-known";
export { posix, win32, Path, DOWNLOADS, DOCUMENTS, PICTURES, DESKTOP, VIDEOS, MUSIC };
}
declare module "socket:path" {
export const sep: "/" | "\\";
export const delimiter: ";";
export const delimiter: ":" | ";";
export const resolve: typeof posix.win32.resolve;
export const join: typeof posix.win32.join;
export const dirname: typeof posix.win32.dirname;
Expand All @@ -1204,7 +1251,13 @@ declare module "socket:path" {
import { posix } from "socket:path/index";
import { Path } from "socket:path/index";
import { win32 } from "socket:path/index";
export { Path, posix, win32 };
import { DOWNLOADS } from "socket:path/index";
import { DOCUMENTS } from "socket:path/index";
import { PICTURES } from "socket:path/index";
import { DESKTOP } from "socket:path/index";
import { VIDEOS } from "socket:path/index";
import { MUSIC } from "socket:path/index";
export { Path, posix, win32, DOWNLOADS, DOCUMENTS, PICTURES, DESKTOP, VIDEOS, MUSIC };
}
declare module "socket:diagnostics/channels" {
/**
Expand Down
30 changes: 27 additions & 3 deletions api/path.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
import { Path, posix, win32 } from './path/index.js'
import { primordials } from './ipc.js'
import {
Path,
posix,
win32,

// well known
DOWNLOADS,
DOCUMENTS,
PICTURES,
DESKTOP,
VIDEOS,
MUSIC
} from './path/index.js'

const isWin32 = primordials.platform === 'win32'

export const sep = isWin32 ? win32.sep : posix.sep
export const delimiter = isWin32 ? win32.delimiter : win32.delimiter
export const delimiter = isWin32 ? win32.delimiter : posix.delimiter

export const resolve = isWin32 ? win32.resolve : posix.resolve
export const join = isWin32 ? win32.join : posix.join
Expand All @@ -18,5 +30,17 @@ export const format = isWin32 ? win32.format : posix.format
export const normalize = isWin32 ? win32.normalize : posix.normalize
export const relative = isWin32 ? win32.relative : posix.relative

export { Path, posix, win32 }
export {
Path,
posix,
win32,

DOWNLOADS,
DOCUMENTS,
PICTURES,
DESKTOP,
VIDEOS,
MUSIC
}

export default isWin32 ? win32 : posix
19 changes: 18 additions & 1 deletion api/path/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,27 @@ import { Path } from './path.js'
import * as posix from './posix.js'
import * as win32 from './win32.js'

import {
DOWNLOADS,
DOCUMENTS,
PICTURES,
DESKTOP,
VIDEOS,
MUSIC
} from './well-known.js'

export * as default from './index.js'

export {
posix,
win32,
Path
Path,

// well known
DOWNLOADS,
DOCUMENTS,
PICTURES,
DESKTOP,
VIDEOS,
MUSIC
}
48 changes: 48 additions & 0 deletions api/path/well-known.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import ipc from '../ipc.js'

const paths = ipc.sendSync('os.paths')

/**
* Well known path to the user's "Downloads" folder.
* @type {?string}
*/
export const DOWNLOADS = paths.data.downloads || null

/**
* Well known path to the user's "Documents" folder.
* @type {?string}
*/
export const DOCUMENTS = paths.data.documents || null

/**
* Well known path to the user's "Pictures" folder.
* @type {?string}
*/
export const PICTURES = paths.data.pictures || null

/**
* Well known path to the user's "Desktop" folder.
* @type {?string}
*/
export const DESKTOP = paths.data.desktop || null

/**
* Well known path to the user's "Videos" folder.
* @type {?string}
*/
export const VIDEOS = paths.data.videos || null

/**
* Well known path to the user's "Music" folder.
* @type {?string}
*/
export const MUSIC = paths.data.music || null

export default {
DOWNLOADS,
DOCUMENTS,
PICTURES,
DESKTOP,
VIDEOS,
MUSIC
}
26 changes: 26 additions & 0 deletions src/android/bridge.kt
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,32 @@ open class Bridge (runtime: Runtime, configuration: IBridgeConfiguration) {
}

when (message.command) {
"os.paths" -> {
val storage = android.os.Environment.getExternalStorageDirectory().absolutePath
val Environment.getExternalStoragePublicDirectory

var downloads = "$storage/Downloads"
var documents = android.os.Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).absolutePath
var pictures = "$storage/Pictures"
var desktop = activity.getExternalFilesDir(null).absolutePath
var videos = "$storage/DCIM/Camera/"
var music = "$storage/Music"
var home = desktop

callback(Result(0, message.seq, message.command, """{
"data": {
"downloads": "$downloads",
"documents": "$documents",
"pictures": "$pictures",
"desktop": "$desktop",
"videos": "$videos",
"music": "$music",
"home": "$home"
}
}"""))
return true
}

"permissions.request" -> {
if (!message.has("name")) {
callback(Result(0, message.seq, message.command, """{
Expand Down
120 changes: 120 additions & 0 deletions src/ipc/bridge.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <format>
#include <regex>
#include <unordered_map>

Expand Down Expand Up @@ -1575,6 +1576,125 @@ static void initRouterTable (Router *router) {
router->core->os.availableMemory(message.seq, RESULT_CALLBACK_FROM_CORE_CALLBACK(message, reply));
});

router->map("os.paths", [](auto message, auto router, auto reply) {
JSON::Object data;

// paths
String downloads;
String documents;
String pictures;
String desktop;
String videos;
String music;
String home;

#if defined(__APPLE__)
static const auto uid = getuid();
static const auto pwuid = getpwuid(uid);
static const auto HOME = pwuid != nullptr
? String(pwuid->pw_dir)
: Env::get("HOME", getcwd());

static const auto fileManager = NSFileManager.defaultManager;

#define DIRECTORY_PATH_FROM_FILE_MANAGER(type) ( \
String([fileManager \
URLForDirectory: type \
inDomain: NSUserDomainMask \
appropriateForURL: nil \
create: NO \
error: nil \
].path.UTF8String) \
)

downloads = DIRECTORY_PATH_FROM_FILE_MANAGER(NSDownloadsDirectory);
documents = DIRECTORY_PATH_FROM_FILE_MANAGER(NSDocumentDirectory);
pictures = DIRECTORY_PATH_FROM_FILE_MANAGER(NSPicturesDirectory);
desktop = DIRECTORY_PATH_FROM_FILE_MANAGER(NSDesktopDirectory);
videos = DIRECTORY_PATH_FROM_FILE_MANAGER(NSMoviesDirectory);
music = DIRECTORY_PATH_FROM_FILE_MANAGER(NSMusicDirectory);
home = String(NSHomeDirectory().UTF8String);

#undef DIRECTORY_PATH_FROM_FILE_MANAGER

#elif defined(__linux__)
static const auto uid = getuid();
static const auto pwuid = getpwuid(uid);
static const auto HOME = pwuid != nullptr
? String(pwuid->pw_dir)
: Env::get("HOME", getcwd());

static const auto XDG_DOCUMENTS_DIR = Env::get("XDG_DOCUMENTS_DIR");
static const auto XDG_DOWNLOAD_DIR = Env::get("XDG_DOWNLOAD_DIR");
static const auto XDG_PICTURES_DIR = Env::get("XDG_PICTURES_DIR");
static const auto XDG_DESKTOP_DIR = Env::get("XDG_DESKTOP_DIR");
static const auto XDG_VIDEOS_DIR = Env::get("XDG_VIDEOS_DIR");
static const auto XDG_MUSIC_DIR = Env::get("XDG_MUSIC_DIR");

if (XDG_DOCUMENTS_DIR.size() > 0) {
documents = XDG_DOCUMENTS_DIR;
} else {
documents = (Path(HOME) / "Documents").string();
}

if (XDG_DOWNLOAD_DIR.size() > 0) {
downloads = XDG_DOWNLOAD_DIR;
} else {
downloads = (Path(HOME) / "Downloads").string();
}

if (XDG_DESKTOP_DIR.size() > 0) {
desktop = XDG_DESKTOP_DIR;
} else {
desktop = (Path(HOME) / "Desktop").string();
}

if (XDG_PICTURES_DIR.size() > 0) {
pictures = XDG_PICTURES_DIR;
} else if (fs::exists(Path(HOME) / "Images")) {
pictures = (Path(HOME) / "Images").string();
} else if (fs::exists(Path(HOME) / "Photos")) {
pictures = (Path(HOME) / "Photos").string();
} else {
pictures = (Path(HOME) / "Pictures").string();
}

if (XDG_VIDEOS_DIR.size() > 0) {
videos = XDG_VIDEOS_DIR
} else {
videos = (Path(HOME) / "Videos").string();
}

if (XDG_MUSIC_DIR.size() > 0) {
music = XDG_MUSIC_DIR;
} else {
music = (Path(HOME) / "Music").string();
}

home = Path(HOME).string();
#elif defined(_WIN32)
static const auto HOME = Env::get("HOMEPATH", Env::get("HOME"));
static const auto USERPROFILE = Env::get("USERPROFILE", HOME)
downloads = (Path(USERPROFILE) / "Downloads").string();
documents = (Path(USERPROFILE) / "Documents").string();
desktop = (Path(USERPROFILE) / "Desktop").string();
pictures = (Path(USERPROFILE) / "Pictures").string();
videos = (Path(USERPROFILE) / "Videos").string();
music = (Path(USERPROFILE) / "Music").string();
home = Path(USERPROFILE).string();
#endif

data["downloads"] = downloads;
data["documents"] = documents;
data["pictures"] = pictures;
data["desktop"] = desktop;
data["videos"] = videos;
data["music"] = music;
data["home"] = home;

return reply(Result::Data { message, data });
});

router->map("permissions.query", [](auto message, auto router, auto reply) {
auto err = validateMessageParameters(message, {"name"});

Expand Down

0 comments on commit 5ef69b3

Please sign in to comment.