Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
434 changes: 392 additions & 42 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"setup": "npm run clean && npm install",
"setup:yarn": "yarn clean && yarn",
"setup:pnpm": "pnpm run clean && pnpm install",
"postinstall": "ts-patch install && husky",
"postinstall": "ts-patch install && husky && patch-package",
"start": "nps"
},
"private": true,
Expand All @@ -28,6 +28,7 @@
"@csstools/css-parser-algorithms": "^3.0.4",
"@csstools/css-tokenizer": "^3.0.3",
"@nativescript/hook": "^3.0.4",
"@nativescript/macos-node-api": "^0.4.0",
"@nativescript/nx": "^22.0.0",
"@nstudio/focus": "^20.0.2",
"@nstudio/nps-i": "~2.0.0",
Expand Down Expand Up @@ -86,6 +87,7 @@
"nx": "22.0.2",
"parse-css": "git+https://github.com/tabatkins/parse-css.git",
"parserlib": "^1.1.1",
"patch-package": "^8.0.1",
"postcss": "^8.0.0",
"postcss-import": "^16.0.0",
"postcss-loader": "^8.0.0",
Expand Down
3 changes: 3 additions & 0 deletions packages/core/animation-frame/animation-native.macos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { time } from '../profiling';

export const getTimeInFrameBase = time;
1 change: 1 addition & 0 deletions packages/core/application-settings/index.macos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './index.ios';
10 changes: 10 additions & 0 deletions packages/core/application/index.macos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ApplicationCommon } from './application-common';

export * from './application-common';
export * from './application-shims';

class MacOSApplication extends ApplicationCommon {
run(): void {}
}

export const Application = new MacOSApplication();
27 changes: 27 additions & 0 deletions packages/core/color/index.macos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ColorBase } from './color-common';
import type { IColor } from './color-types';

export class Color extends ColorBase implements IColor {
private _macos: NSColor;

get ios(): any {
if (!this._macos) {
this._macos = NSColor.colorWithSRGBRedGreenBlueAlpha(this.r / 255, this.g / 255, this.b / 255, this.a / 255);
}

return this._macos;
}

public static fromIosColor(value: any): Color {
if (!value) {
return null;
}

const color = value as NSColor;
const r = Math.round((color.redComponent ?? 0) * 255);
const g = Math.round((color.greenComponent ?? 0) * 255);
const b = Math.round((color.blueComponent ?? 0) * 255);
const a = Math.round((color.alphaComponent ?? 1) * 255);
return new Color(a, r, g, b);
}
}
1 change: 1 addition & 0 deletions packages/core/file-system/file-system-access.macos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './file-system-access.ios';
30 changes: 30 additions & 0 deletions packages/core/fps-meter/fps-native.macos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export class FPSCallback {
public running = false;
private readonly onFrame: (currentTimeMillis: number) => void;
private handle: any;

constructor(onFrame: (currentTimeMillis: number) => void) {
this.onFrame = onFrame;
}

public start() {
if (this.running) {
return;
}

this.running = true;
this.handle = setInterval(() => {
this.onFrame(Date.now());
}, 16);
}

public stop() {
if (!this.running) {
return;
}

this.running = false;
clearInterval(this.handle);
this.handle = null;
}
}
186 changes: 186 additions & 0 deletions packages/core/http/http-request/index.macos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import * as types from '../../utils/types';
import * as domainDebugger from '../../debugger';
import { getFilenameFromUrl } from './http-request-common';
import { File } from '../../file-system';
import type { HttpRequestOptions, HttpResponse, Headers } from '../http-interfaces';
import { HttpResponseEncoding } from '../http-interfaces';

const GET = 'GET';
const USER_AGENT_HEADER = 'User-Agent';
const USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko)';

const sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration;
const queue = NSOperationQueue.mainQueue;

function parseJSON(source: string): any {
const src = source.trim();
if (src.lastIndexOf(')') === src.length - 1) {
return JSON.parse(src.substring(src.indexOf('(') + 1, src.lastIndexOf(')')));
}
return JSON.parse(src);
}

let defaultSession: NSURLSession;
function ensureDefaultSession() {
if (!defaultSession) {
defaultSession = NSURLSession.sessionWithConfigurationDelegateDelegateQueue(sessionConfig, null, queue);
}
}

export function request(options: HttpRequestOptions): Promise<HttpResponse> {
return new Promise<HttpResponse>((resolve, reject) => {
if (!options.url) {
reject(new Error('Request url was empty.'));
return;
}

try {
const network = domainDebugger.getNetwork();
const debugRequest = network && network.create();
const urlRequest = NSMutableURLRequest.requestWithURL(NSURL.URLWithString(options.url));

urlRequest.HTTPMethod = types.isDefined(options.method) ? options.method : GET;
urlRequest.setValueForHTTPHeaderField(USER_AGENT, USER_AGENT_HEADER);

if (options.headers) {
for (const header in options.headers) {
urlRequest.setValueForHTTPHeaderField(options.headers[header] + '', header);
}
}

if (types.isString(options.content) || options.content instanceof FormData) {
urlRequest.HTTPBody = NSString.stringWithString(options.content.toString()).dataUsingEncoding(NSUTF8StringEncoding);
} else if (options.content instanceof ArrayBuffer) {
urlRequest.HTTPBody = NSData.dataWithData(options.content as any);
}

if (types.isNumber(options.timeout)) {
urlRequest.timeoutInterval = options.timeout / 1000;
}

ensureDefaultSession();

let timestamp = -1;
const dataTask = defaultSession.dataTaskWithRequestCompletionHandler(urlRequest, (data: NSData, response: NSHTTPURLResponse, error: NSError) => {
if (error) {
reject(new Error(error.localizedDescription));
return;
}

const headers: Headers = {};
if (response && response.allHeaderFields) {
const headerFields = response.allHeaderFields;
headerFields.enumerateKeysAndObjectsUsingBlock((key, value) => {
addHeader(headers, key, value);
});
}

if (debugRequest) {
debugRequest.mimeType = response.MIMEType;
debugRequest.data = data;
const debugResponse = {
url: options.url,
status: response.statusCode,
statusText: NSHTTPURLResponse.localizedStringForStatusCode(response.statusCode),
headers: headers,
mimeType: response.MIMEType,
fromDiskCache: false,
timing: {
requestTime: timestamp,
proxyStart: -1,
proxyEnd: -1,
dnsStart: -1,
dnsEnd: -1,
connectStart: -1,
connectEnd: -1,
sslStart: -1,
sslEnd: -1,
serviceWorkerFetchStart: -1,
serviceWorkerFetchReady: -1,
serviceWorkerFetchEnd: -1,
sendStart: -1,
sendEnd: -1,
receiveHeadersEnd: -1,
},
headersSize: headers?.length ?? -1,
};
debugRequest.responseReceived(debugResponse);
debugRequest.loadingFinished();
}

resolve({
content: {
raw: data,
toArrayBuffer: () => interop.bufferFromData(data),
toString: (encoding?: any) => {
const str = NSDataToString(data, encoding);
if (typeof str === 'string') {
return str;
}
throw new Error('Response content may not be converted to string');
},
toJSON: (encoding?: any) => parseJSON(NSDataToString(data, encoding)),
toImage: () => Promise.reject(new Error('Response content may not be converted to an Image on macOS')),
toFile: (destinationFilePath?: string) => {
if (!destinationFilePath) {
destinationFilePath = getFilenameFromUrl(options.url);
}
if (data instanceof NSData) {
const file = File.fromPath(destinationFilePath);
data.writeToFileAtomically(destinationFilePath, true);
return file;
}
throw new Error(`Cannot save file with path: ${destinationFilePath}.`);
},
},
statusCode: response.statusCode,
headers: headers,
});
});

if (options.url && debugRequest) {
timestamp = Date.now() / 1000;
const request = {
url: options.url,
method: 'GET',
headers: options.headers,
timestamp,
headersSize: options?.headers?.length ?? -1,
};
debugRequest.requestWillBeSent(request);
}

dataTask.resume();
} catch (ex) {
reject(ex);
}
});
}

function NSDataToString(data: any, encoding?: HttpResponseEncoding): string {
let code = NSUTF8StringEncoding;

if (encoding === HttpResponseEncoding.GBK) {
code = CFStringEncodings.kCFStringEncodingGB_18030_2000;
}

let encodedString = NSString.alloc().initWithDataEncoding(data, code);
if (!encodedString) {
code = NSISOLatin1StringEncoding;
encodedString = NSString.alloc().initWithDataEncoding(data, code);
}

return encodedString.toString();
}

export function addHeader(headers: Headers, key: string, value: string): void {
if (!headers[key]) {
headers[key] = value;
} else if (Array.isArray(headers[key])) {
(<string[]>headers[key]).push(value);
} else {
const values: string[] = [<string>headers[key]];
values.push(value);
headers[key] = values;
}
}
85 changes: 85 additions & 0 deletions packages/core/http/index.macos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { type ImageSourceLike } from './http-shared';
import { request } from './http-request';
export { request } from './http-request';
export * from './http-interfaces';

export function getString(arg: any): Promise<string> {
return new Promise<string>((resolve, reject) => {
request(typeof arg === 'string' ? { url: arg, method: 'GET' } : arg).then(
(r) => {
try {
const str = r.content.toString();
resolve(str);
} catch (e) {
reject(e);
}
},
(e) => reject(e),
);
});
}

export function getJSON<T>(arg: any): Promise<T> {
return new Promise<T>((resolve, reject) => {
request(typeof arg === 'string' ? { url: arg, method: 'GET' } : arg).then(
(r) => {
try {
const json = r.content.toJSON();
resolve(json);
} catch (e) {
reject(e);
}
},
(e) => reject(e),
);
});
}

export function getImage(arg: any): Promise<ImageSourceLike> {
return new Promise<any>((resolve, reject) => {
request(typeof arg === 'string' ? { url: arg, method: 'GET' } : arg).then(
(r) => {
try {
resolve(r.content.toImage());
} catch (err) {
reject(err);
}
},
(err) => {
reject(err);
},
);
});
}

export function getFile(arg: any, destinationFilePath?: string): Promise<any> {
return new Promise<any>((resolve, reject) => {
request(typeof arg === 'string' ? { url: arg, method: 'GET' } : arg).then(
(r) => {
try {
const file = r.content.toFile(destinationFilePath);
resolve(file);
} catch (e) {
reject(e);
}
},
(e) => reject(e),
);
});
}

export function getBinary(arg: any): Promise<ArrayBuffer> {
return new Promise<ArrayBuffer>((resolve, reject) => {
request(typeof arg === 'string' ? { url: arg, method: 'GET' } : arg).then(
(r) => {
try {
const arrayBuffer = r.content.toArrayBuffer();
resolve(arrayBuffer);
} catch (e) {
reject(e);
}
},
(e) => reject(e),
);
});
}
9 changes: 9 additions & 0 deletions packages/core/index.macos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export * as ApplicationSettings from './application-settings';
export { File, FileSystemEntity, Folder, knownFolders, path, getFileAccess, AndroidDirectory } from './file-system';
export type { HttpRequestOptions, HttpResponse, Headers, HttpContent } from './http/http-interfaces';
export { HttpResponseEncoding } from './http/http-interfaces';
export * as Http from './http';
export { isAndroid, isIOS, isVisionOS, isApple, Screen, Device, platformNames } from './platform';
export type { IDevice } from './platform';
export * as Utils from './utils';
export * as Dialogs from './ui/dialogs';
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nativescript/core",
"version": "9.0.14-next.1",
"version": "9.1.0-alpha.2",
"description": "A JavaScript library providing an easy to use api for interacting with iOS and Android platform APIs.",
"type": "module",
"main": "index",
Expand Down
Loading
Loading