Initial nativescript testing
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 2m24s
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 2m24s
This commit is contained in:
parent
fdb179d183
commit
4c21600576
1
apps/blakus-nativescript/.gitignore
vendored
1
apps/blakus-nativescript/.gitignore
vendored
@ -8,7 +8,6 @@ platforms/
|
||||
*.js
|
||||
!eslint.config.js
|
||||
!webpack.config.js
|
||||
!tailwind.config.js
|
||||
|
||||
# Logs
|
||||
logs
|
||||
|
||||
@ -14,6 +14,9 @@
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||
|
||||
<application
|
||||
android:name="com.tns.NativeScriptApplication"
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="_amenity_restaurant_CYImm">"Restaurant"</string>
|
||||
<string name="_amenity_pub_hVjSx">"Pub"</string>
|
||||
<string name="_amenity_ice_cream_12K4Gu">"Ice Cream"</string>
|
||||
<string name="_amenity_food_court_Z2qUk6P">"Food Court"</string>
|
||||
<string name="_amenity_fast_food_Z1zDs8J">"Fast Food"</string>
|
||||
<string name="_amenity_cafe_Z13hX6o">"Cafe"</string>
|
||||
<string name="_amenity_biergarten_zXiC4">"Beer Garden"</string>
|
||||
<string name="_amenity_bar_hVg75">"Bar"</string>
|
||||
<string name="_app_name_1k3Sbz">"Blakus"</string>
|
||||
<string name="app_name">"Blakus"</string>
|
||||
<string name="title_activity_kimera">"Blakus"</string>
|
||||
</resources>
|
||||
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="_amenity_restaurant_CYImm">"Restorāns"</string>
|
||||
<string name="_amenity_pub_hVjSx">"Krogs"</string>
|
||||
<string name="_amenity_ice_cream_12K4Gu">"Saldējums"</string>
|
||||
<string name="_amenity_food_court_Z2qUk6P">"Ēdināšanas laukums"</string>
|
||||
<string name="_amenity_fast_food_Z1zDs8J">"Ātras uzkodas"</string>
|
||||
<string name="_amenity_cafe_Z13hX6o">"Kafejnīca"</string>
|
||||
<string name="_amenity_biergarten_zXiC4">"Biergarten"</string>
|
||||
<string name="_amenity_bar_hVg75">"Bārs"</string>
|
||||
<string name="_app_name_1k3Sbz">"Blakus"</string>
|
||||
<string name="app_name">"Blakus"</string>
|
||||
<string name="title_activity_kimera">"Blakus"</string>
|
||||
</resources>
|
||||
@ -4,11 +4,12 @@
|
||||
"license": "SEE LICENSE IN <your-license-filename>",
|
||||
"repository": "<fill-your-repository-here>",
|
||||
"dependencies": {
|
||||
"@nativescript/core": "*"
|
||||
"@nativescript/core": "*",
|
||||
"@nativescript/geolocation": "^9.0.0",
|
||||
"@nativescript/localize": "^5.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nativescript/android": "~8.8.0",
|
||||
"@nativescript/ios": "~8.8.0",
|
||||
"@nativescript/tailwind": "^2.1.0"
|
||||
"@nativescript/ios": "~8.8.0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1 +1,7 @@
|
||||
|
||||
.ns-root {
|
||||
--base-color: red;
|
||||
}
|
||||
|
||||
Button {
|
||||
background-color: var(--base-color);
|
||||
}
|
||||
@ -1,3 +1,7 @@
|
||||
import { Application } from '@nativescript/core';
|
||||
import { localize } from '@nativescript/localize';
|
||||
|
||||
Application.setResources({ L: localize })
|
||||
|
||||
Application.run({ moduleName: 'app-root' });
|
||||
console.log(localize('app.name'));
|
||||
13
apps/blakus-nativescript/src/i18n/en.json
Normal file
13
apps/blakus-nativescript/src/i18n/en.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"app.name": "Blakus",
|
||||
"amenity": {
|
||||
"bar": "Bar",
|
||||
"biergarten": "Beer Garden",
|
||||
"cafe": "Cafe",
|
||||
"fast_food": "Fast Food",
|
||||
"food_court": "Food Court",
|
||||
"ice_cream": "Ice Cream",
|
||||
"pub": "Pub",
|
||||
"restaurant": "Restaurant"
|
||||
}
|
||||
}
|
||||
13
apps/blakus-nativescript/src/i18n/lv.default.json
Normal file
13
apps/blakus-nativescript/src/i18n/lv.default.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"app.name": "Blakus",
|
||||
"amenity": {
|
||||
"bar": "Bārs",
|
||||
"biergarten": "Biergarten",
|
||||
"cafe": "Kafejnīca",
|
||||
"fast_food": "Ātras uzkodas",
|
||||
"food_court": "Ēdināšanas laukums",
|
||||
"ice_cream": "Saldējums",
|
||||
"pub": "Krogs",
|
||||
"restaurant": "Restorāns"
|
||||
}
|
||||
}
|
||||
32
apps/blakus-nativescript/src/location.ts
Normal file
32
apps/blakus-nativescript/src/location.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import * as geolocation from '@nativescript/geolocation';
|
||||
import { CoreTypes } from '@nativescript/core'
|
||||
|
||||
export class DeviceLocation {
|
||||
static async getDeviceLocation() {
|
||||
try {
|
||||
|
||||
// Enable location services
|
||||
await geolocation.enableLocationRequest(false, true);
|
||||
|
||||
const enabled = await geolocation.isEnabled();
|
||||
|
||||
console.log('what do we got?', enabled)
|
||||
|
||||
// Get the current location
|
||||
const location = await geolocation.getCurrentLocation({
|
||||
desiredAccuracy: CoreTypes.Accuracy.high,
|
||||
maximumAge: 5000,
|
||||
timeout: 20000,
|
||||
});
|
||||
|
||||
if (location) {
|
||||
console.log(`Latitude: ${location.latitude}, Longitude: ${location.longitude}`);
|
||||
return location;
|
||||
} else {
|
||||
throw new Error('Could not get the location.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error obtaining location:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,22 @@
|
||||
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" class="page">
|
||||
<Page.actionBar>
|
||||
<ActionBar title="My App" icon="" class="action-bar">
|
||||
<ActionBar title="Blakus" icon="" class="action-bar">
|
||||
</ActionBar>
|
||||
</Page.actionBar>
|
||||
<StackLayout class="p-20">
|
||||
<Label text="Tap the button" class="h1 text-center"/>
|
||||
<Button text="TAP" tap="{{ onTap }}" class="btn btn-primary btn-active"/>
|
||||
<Button text="TAP" tap="{{ onTap }}" />
|
||||
<Button text="Location" tap="{{ onLocationTap }}" />
|
||||
<Label text="{{ message }}" class="h2 text-center" textWrap="true"/>
|
||||
<ListView items="{{ items }}" itemTap="{{ onItemTap }}">
|
||||
<ListView.itemTemplate>
|
||||
<!-- The item template can only have a single root element -->
|
||||
<GridLayout padding="16" columns="20, *, *">
|
||||
<ContentView width="20" height="20" borderRadius="20" backgroundColor="#65adf1" />
|
||||
<Label text="{{ title }}" col="1" textWrap="true" marginLeft="8" />
|
||||
<Label text="{{ L(`amenity.${amenity}`) }}" col="2" />
|
||||
</GridLayout>
|
||||
</ListView.itemTemplate>
|
||||
</ListView>
|
||||
</StackLayout>
|
||||
</Page>
|
||||
|
||||
@ -1,8 +1,53 @@
|
||||
import { Observable } from '@nativescript/core';
|
||||
import { Observable, Http, type ItemEventData, ListView } from '@nativescript/core';
|
||||
import { DeviceLocation } from './location';
|
||||
import type { Location } from '@nativescript/geolocation';
|
||||
import { localize } from '@nativescript/localize';
|
||||
|
||||
type ReverseGeocodeResult = {
|
||||
valsts: string;
|
||||
admin_vien: string;
|
||||
terit_vien: string;
|
||||
apdz_vieta: string;
|
||||
iela: string;
|
||||
maja: string;
|
||||
index: string;
|
||||
korpus: string;
|
||||
vzd_id: string;
|
||||
distance: number;
|
||||
x: string;
|
||||
y: string;
|
||||
lon: number;
|
||||
lat: number;
|
||||
adrese: string;
|
||||
}
|
||||
|
||||
type BlakusItem = {
|
||||
title: string;
|
||||
amenity: string;
|
||||
tags: Record<string, string>;
|
||||
}
|
||||
|
||||
type OverpassResult = {
|
||||
version: number;
|
||||
generator: string;
|
||||
osm3s: Record<string, string>;
|
||||
elements: {
|
||||
type: string,
|
||||
id: number,
|
||||
tags: Record<string, string>;
|
||||
}[]
|
||||
}
|
||||
|
||||
async function aWait(timeout: number) {
|
||||
return new Promise(resolve => setTimeout(resolve, timeout));
|
||||
}
|
||||
|
||||
export class HelloWorldModel extends Observable {
|
||||
private _counter: number;
|
||||
private _message: string;
|
||||
private _items: BlakusItem[];
|
||||
private _locationServiceBaseURL = 'https://api.kartes.lv/v3/KVDM_mwwKi/'
|
||||
private _overpassBaseURL = 'https://overpass-api.de/api/';
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@ -23,17 +68,115 @@ export class HelloWorldModel extends Observable {
|
||||
}
|
||||
}
|
||||
|
||||
onTap() {
|
||||
this._counter--;
|
||||
this.updateMessage();
|
||||
get items(): BlakusItem[] {
|
||||
return this._items || [];
|
||||
}
|
||||
|
||||
private updateMessage() {
|
||||
if (this._counter <= 0) {
|
||||
this.message =
|
||||
'Hoorraaay! You unlocked the NativeScript clicker achievement!';
|
||||
} else {
|
||||
this.message = `${this._counter} taps left`;
|
||||
set items(value: BlakusItem[]) {
|
||||
if (this._items !== value) {
|
||||
this._items = value;
|
||||
this.notifyPropertyChange('items', value);
|
||||
}
|
||||
}
|
||||
|
||||
async reverseGeocode({latitude, longitude}: Location) {
|
||||
const params = new URLSearchParams();
|
||||
params.set('lat', latitude.toString());
|
||||
params.set('lon', longitude.toString());
|
||||
|
||||
this.message = [latitude, longitude].join(', ');
|
||||
|
||||
const url = new URL(`reverse_geocoding?${params}`, this._locationServiceBaseURL).toString();
|
||||
const result = await Http.getJSON<ReverseGeocodeResult>(url);
|
||||
console.log(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
overpassQuery(query: string) {
|
||||
const url = new URL(`interpreter?data=${encodeURIComponent(query)}`, this._overpassBaseURL).toString();
|
||||
console.log('overpass query', url)
|
||||
return Http.getJSON<OverpassResult>(url)
|
||||
}
|
||||
|
||||
async getOverpassAmenities({latitude, longitude}: Location) {
|
||||
const radius = 1000; // meters
|
||||
const query = `
|
||||
[out:json][timeout:25];
|
||||
node["amenity"](around:${radius}, ${latitude}, ${longitude});
|
||||
out tags;
|
||||
`;
|
||||
const result = await this.overpassQuery(query);
|
||||
console.log('yep');
|
||||
console.log(Array.from(new Set(result.elements.map(el => el.tags['amenity']))));
|
||||
}
|
||||
|
||||
async getOverpassInfo({latitude, longitude}: Location) {
|
||||
|
||||
const radius = 1000; // meters
|
||||
const amenities = ['restaurant', 'cafe', 'bar', 'pub', 'biergarten', 'fast_food', 'food_court', 'ice_cream'];
|
||||
|
||||
const query = `
|
||||
[out:json];
|
||||
node(around:${radius}, ${latitude}, ${longitude})["amenity"~"${amenities.join('|')}"];
|
||||
out body;
|
||||
>;
|
||||
out skel qt;
|
||||
`;
|
||||
|
||||
const result = await this.overpassQuery(query);
|
||||
this.items = result.elements
|
||||
.map(({ tags }) => ({ title: tags.name, amenity: tags.amenity, tags}))
|
||||
.filter(i => amenities.includes(i.amenity)); // query returns some random results. need to look into this
|
||||
|
||||
console.log(localize('app.name'))
|
||||
|
||||
console.log(result.elements);
|
||||
}
|
||||
|
||||
async postalPolygons(country = 'LV', code: string, mode: 'isolate' | 'collect' | 'union' = 'union') {
|
||||
await aWait(1000);
|
||||
const params = new URLSearchParams();
|
||||
if (code.length === 4) params.set('search', `${country}-${code}`);
|
||||
if (code.length == 2) params.set('groups', `${country}-${code}`)
|
||||
params.set('union_mode', mode);
|
||||
params.set('wgs84', '');
|
||||
// params.set('wkt', '');
|
||||
const url = new URL(`postal_codes?${params}`, this._locationServiceBaseURL).toString();
|
||||
|
||||
const result = await Http.getJSON(url);
|
||||
console.log(url);
|
||||
console.log(result);
|
||||
|
||||
}
|
||||
|
||||
async onLocationTap() {
|
||||
const location = await DeviceLocation.getDeviceLocation();
|
||||
await this.getOverpassInfo(location);
|
||||
// await this.getOverpassAmenities(location);
|
||||
// const { index } = await this.reverseGeocode(location);
|
||||
// const [country, code] = index.split('-');
|
||||
// await this.postalPolygons(country, code);
|
||||
|
||||
|
||||
}
|
||||
|
||||
onTap() {
|
||||
this._counter--;
|
||||
|
||||
if (this._counter <= 0) {
|
||||
this.updateMessage('Hoorraaay! You unlocked the NativeScript clicker achievement!');
|
||||
} else {
|
||||
this.updateMessage(`${this._counter} taps left`);
|
||||
}
|
||||
}
|
||||
|
||||
onItemTap(args: ItemEventData) {
|
||||
const listView = args.object as ListView
|
||||
console.log('Tapped item', listView.items[args.index])
|
||||
}
|
||||
|
||||
private updateMessage(message = "") {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ['./src/**/*.{css,xml,html,vue,svelte,ts,tsx}'],
|
||||
// use the .ns-dark class to control dark mode (applied by NativeScript) - since 'media' (default) is not supported.
|
||||
darkMode: ['class', '.ns-dark'],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
corePlugins: {
|
||||
preflight: false, // disables browser-specific resets
|
||||
},
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user