-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tabris.js router #34
Open
ahmadov
wants to merge
2
commits into
master
Choose a base branch
from
tabris-router
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Tabris.js router #34
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Example "router" | ||
|
||
[![GitPod Logo](../../doc/run-in-gitpod.png)](https://gitpod.io/#example=router/https://github.com/eclipsesource/tabris-decorators/tree/tabris-router/examples/router) | ||
|
||
## Description | ||
|
||
Demonstrates the usage of the router API. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"name": "router", | ||
"version": "3.3.0", | ||
"dependencies": { | ||
"reflect-metadata": "^0.1.13" | ||
}, | ||
"optionalDependencies": { | ||
"tabris": "^3.3.0", | ||
"tabris-decorators": "3.3.0" | ||
}, | ||
"devDependencies": { | ||
"typescript": "3.3.x" | ||
}, | ||
"main": "dist/app.js", | ||
"scripts": { | ||
"start": "tabris serve -w -a", | ||
"build": "tsc -p .", | ||
"watch": "tsc -p . -w --preserveWatchOutput --inlineSourceMap", | ||
"gitpod": "tabris serve -a -w --no-intro --port 8080 --external $(gp url 8080):443" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import {NavigationView, contentView, Button, TextView, TextInput, Stack, Page, Properties} from 'tabris'; | ||
import {Router, Route, injectable, create, resolve, property, component } from 'tabris-decorators'; | ||
|
||
const navigationView = new NavigationView({ | ||
layoutData: 'stretch' | ||
}).appendTo(contentView); | ||
|
||
class MyPage1 extends Page { | ||
constructor(properties?: Properties<MyPage1>) { | ||
super(properties); | ||
this.append( | ||
<Stack stretch alignment="stretchX" padding={[0, 4]}> | ||
<TextInput/> | ||
<Button text="Open" onSelect={() => | ||
router.goTo({ | ||
route: 'MyRoute2', | ||
payload: { | ||
text: this.find(TextInput).only().text | ||
} | ||
})} | ||
/> | ||
</Stack> | ||
); | ||
} | ||
} | ||
|
||
@component | ||
class MyPage2 extends Page { | ||
@property text: string; | ||
|
||
constructor(properties?: Properties<MyPage2>) { | ||
super(properties); | ||
this.append( | ||
<Stack stretch alignment="stretchX" padding={[0, 4]}> | ||
<TextView alignment="centerX" height={32} bind-text="text"/> | ||
<Button text="Go back" onSelect={() => router.back()}/> | ||
<TextInput bind-text="text" /> | ||
<Button text="Open" onSelect={() => | ||
router.goTo({ | ||
route: 'MyRoute2', | ||
payload: { | ||
text: this._find(TextInput).only().text | ||
} | ||
})} | ||
/> | ||
</Stack> | ||
); | ||
} | ||
} | ||
|
||
@injectable({ param: 'MyRoute1' }) | ||
class MyRoute1 extends Route { | ||
page = new MyPage1({title: 'foo'}); | ||
}; | ||
|
||
@injectable({ param: 'MyRoute2' }) | ||
class MyRoute2 extends Route { | ||
page = new MyPage2({title: 'bar'}); | ||
}; | ||
|
||
const router = new Router({ | ||
navigationView, | ||
history: [{ route: 'MyRoute1' }] | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"compilerOptions": { | ||
"module": "commonjs", | ||
"target": "es6", | ||
"lib": ["es6" ], | ||
"jsx": "react", | ||
"jsxFactory": "JSX.createElement", | ||
"outDir": "dist", | ||
"experimentalDecorators": true, | ||
"emitDecoratorMetadata": true, | ||
"typeRoots": ["./node_modules/@types"] | ||
}, | ||
"include": [ | ||
"./src/*.ts", | ||
"./src/*.tsx" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { Page } from "tabris"; | ||
|
||
export type Dictionary<T> = { [key: string]: T }; | ||
|
||
export class Route<PayloadType = Dictionary<string>> { | ||
page: Page; | ||
payload?: PayloadType; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import { NavigationView } from "tabris"; | ||
import { ListLike, Mutation } from "../List"; | ||
import { RouterMatcher } from "./RouterMatcher"; | ||
import { RouterHistory, HistoryItem } from "./RouterHistory"; | ||
import { Route } from "./Route"; | ||
|
||
export type RouterProperties = { | ||
navigationView: NavigationView, | ||
defaultRoute?: HistoryItem, | ||
history?: ListLike<HistoryItem> | ||
}; | ||
|
||
export class Router<ItemType extends HistoryItem = HistoryItem> { | ||
|
||
private _navigationView: NavigationView; | ||
private _routerHistoryObserver: RouterHistory; | ||
private _routerMatcher: RouterMatcher; | ||
|
||
constructor({navigationView, history} : RouterProperties) { | ||
this._navigationView = navigationView; | ||
this._routerHistoryObserver = new RouterHistory(this._handleHistoryChange); | ||
this._routerMatcher = new RouterMatcher(); | ||
this.history = history || []; | ||
this._navigationView.onRemoveChild(this._syncHistoryWithNavigationView.bind(this)); | ||
} | ||
|
||
goTo(item: ItemType) { | ||
this._routerHistoryObserver.push(item); | ||
} | ||
|
||
back() { | ||
if (this._routerHistoryObserver.history.length === 0) { | ||
throw new Error("Could not call back on empty history stack"); | ||
} | ||
this._routerHistoryObserver.pop(); | ||
} | ||
|
||
set history(value: ListLike<HistoryItem>) { | ||
this._routerHistoryObserver.history = value; | ||
} | ||
|
||
get history() { | ||
return this._routerHistoryObserver.history; | ||
} | ||
|
||
protected _handleHistoryChange = ({deleteCount, items}: Mutation<ItemType>) => { | ||
if (deleteCount > items.length) { | ||
this._disposeRoutes(deleteCount); | ||
} else if (items.length > deleteCount) { | ||
this._appendRoutes(items); | ||
} | ||
} | ||
|
||
private _disposeRoutes(count: number = 0) { | ||
if (count <= 0) { | ||
return; | ||
} | ||
const size = this._navigationView.children().length; | ||
this._navigationView | ||
.children() | ||
.slice(size - count) | ||
.forEach(child => child.dispose()); | ||
} | ||
|
||
private _appendRoutes(routes: ListLike<ItemType>) { | ||
routes.forEach(item => { | ||
const route = this._routerMatcher.match(item); | ||
this._appendRoute(route, item.payload); | ||
}); | ||
} | ||
|
||
private _appendRoute(route: Route, payload?: object) { | ||
if (payload) { | ||
for (const key of Object.keys(payload)) { | ||
if (key in route.page) { | ||
route.page[key] = payload[key]; | ||
} | ||
} | ||
} | ||
this._navigationView.append(route.page); | ||
} | ||
|
||
private _syncHistoryWithNavigationView() { | ||
while (this.history.length !== this._navigationView.children().length) { | ||
this._routerHistoryObserver.removeLast(); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { ListLikeObvserver } from "../../internals/ListLikeObserver"; | ||
import { Mutation, List, ListLike } from "../List"; | ||
import { Dictionary } from "./Route"; | ||
|
||
export type HistoryItem = { route: string, payload?: Dictionary<string> }; | ||
|
||
export class RouterHistory<T extends HistoryItem = HistoryItem> { | ||
|
||
private _observer: ListLikeObvserver<T>; | ||
|
||
constructor(_callback: (ev: Mutation<T>) => void) { | ||
this._observer = new ListLikeObvserver<T>(_callback); | ||
} | ||
|
||
public push(item: T) { | ||
const source = this.getSource(); | ||
source.push(item); | ||
this._observer.source = source; | ||
} | ||
|
||
public pop(): T { | ||
const source = this.getSource(); | ||
const result = source.pop(); | ||
this._observer.source = source; | ||
return result; | ||
} | ||
|
||
public removeLast() { | ||
return this._observer.source.pop(); | ||
} | ||
|
||
get history() { | ||
return this._observer.source; | ||
} | ||
|
||
set history(value: ListLike<T>) { | ||
this._observer.source = value; | ||
} | ||
|
||
get current() { | ||
return this._observer.source[this._observer.source.length - 1]; | ||
} | ||
|
||
private getSource() { | ||
if (this._observer.source instanceof Array) { | ||
return Array.from(this._observer.source); | ||
} else if (this._observer.source instanceof List) { | ||
return List.from(this._observer.source); | ||
} | ||
throw new Error('Unsupported type'); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { Route } from "./Route"; | ||
import { HistoryItem } from './RouterHistory'; | ||
import { resolve } from "../.."; | ||
|
||
export class RouterMatcher { | ||
match(historyItem: HistoryItem): Route { | ||
const name = historyItem.route; | ||
const route = this._createRoute(name); | ||
if (!route) { | ||
throw new Error(`Route with '${name}' name does not exist!`); | ||
} | ||
return route; | ||
} | ||
|
||
private _createRoute(name: string): Route { | ||
return resolve(Route, name); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But you don't know where in the history the items were deleted. This assumes it's at the end. It also doesn't handle replacement.