Ionic2 Push Notification Page move - push-notification

I made Ionic2 App with notification using this plugin https://github.com/phonegap/phonegap-plugin-push. When the users receive the notification, depending on its data, I would like them to move the page accordingly.
I am sending route to additionalData to distinguish which page to guide them. In addition to this, I want to guide the user to specific tab of the page.
Any suggestion or advice would be appreciated!
Thank you in advance.
app.components.ts
declare var TabIndex: any;
.....
push.on('notification').subscribe((notification:any) => {
if (notification.additionalData.route == 'order-list') {
console.log('order-list is selected');
//WHAT DO I DO?
//I want the user to move to TabsPage(parent view) and its second-tab(child view)
} else if (notification.additionalData.route == 'personal') {
console.log('personal is selected');
//I want the user to move to TabsPage and its third-tab
}
});
EDITED:
app.components.ts
push.on('notification').subscribe((notification:any) => {
if (notification.additionalData.AppRoute == 'order-list') {
console.log('move to orderlist');
// this.nav.push(TabsPage, {"index" : 1});
TabIndex = 1;
} else if (notification.additionalData.AppRoute == 'order-home') {
console.log('move to home');
// this.nav.push(TabsPage, {"index" : 0});
TabIndex = 0;
}
});
tabs.ts
constructor(private navParams: NavParams) {
if (TabIndex) {
this.index = TabIndex;
}
}

You can have navParams in your Tabs.ts (as in where the tabs are mentioned and in Tabs.html, you set it using <ion-tabs>).
You can send index of tab as navParam to this tabs.ts. Then, use <ion-tabs selectedIndex="2"> in this page.
tabs.ts:
export TabsPage{
index = 1;
constructor(private navParams: NavParams){
// This if() is for other cases where you don't want to send navParams. Like normally setting this page and selectedTab to 1.
if(this.navParams.data.index !== undefined){
index = this.navParams.data.index;
}
}
}
tabs.html :
<ion-tabs selectedIndex={{index}}>
<ion-tab>..</ion-tab>
...
</ion-tabs>
And app.component.ts:
push.on('notification').subscribe((notification:any) => {
if (notification.additionalData.route == 'order-list') {
console.log('order-list is selected');
this.nav.push(TabsPage, {"index" : 2});
} else if (notification.additionalData.route == 'personal') {
console.log('personal is selected');
this.nav.push(TabsPage, {"index" : 3});
}
});

Related

Flutter code in widgetsBinding.instance.addPostFrameCallback getting called multiple times

I am building a sign in functionality using bloc pattern, if the entered credentials are invalid, bloc will return a authErrorState, so I will display a invalid credentials popup as soon as the bloc return a authError State
please check the code :
if (state is IsAuthLoadingState) {
return const LoadingSpinnerWidget();
} else if (state is IsAuthenticatedState) {
WidgetsBinding.instance.addPostFrameCallback((_) {
stopTimer();
BlocProvider.of<AuthBloc>(context).add(LoadAuthStatus());
Navigator.pop(context, true);
});
} else if (state is AuthErrorState) {
WidgetsBinding.instance.addPostFrameCallback((_) {
stopTimer();
showCustomPopUp(state.message);
});
}
Bloc code :
void _onLoginUser(LoginUser event, Emitter<AuthState> emit) async {
emit(IsAuthLoadingState());
final UserLoggedInResponse userDetails =
await authRepository.handleLoginUser(event.phoneNumber, event.otp);
if (userDetails.status == "success") {
for (var item in userDetails.wishlist) {
await _localRepo.addWishlistItem(item);
}
for (var item in userDetails.cart) {
await _localRepo.addCartItem(item);
}
for (var item in userDetails.recentSearches) {
await _localRepo.addRecentSearchTerm(item);
}
await _localRepo.addPurchasedItems(userDetails.purchasedItemIds);
await _localRepo.setIsAuthenticated(
userDetails.accessToken, userDetails.userId);
emit(IsAuthenticatedState());
} else {
emit(AuthErrorState(
message: userDetails.message, content: userDetails.content));
}
}
But, the invalid credentials popup written in authErrorState is getting called multiple times.
Any help is really appreciated. Thank you.
As I didn't found any alternative options, I someone tried to manage this for now like this,
I used a bool variable called isErrorShown, and it was set to false by default,
once the code in widgetsBinding is executed, it will set the isErrorShown to true, function is widgetsBinding checks the value of isErrorShown and executes only if it is false :
else if (state is AuthErrorState) {
print("error state");
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!isErrorShown) {
stopTimer();
if (state.message ==
"user does not exits, please create user") {
Navigator.pushReplacementNamed(context, '/create-user',
arguments: CreateUserPage(
showProfile: widget.showProfile,
phoneNumber: phoneNumberController.text,
otp: otpController.text,
));
// BlocProvider.of<AuthBloc>(context).add(LoadAuthStatus());
// Navigator.pushNamed(context, '/create-user');
} else {
showCustomPopUp(state.message);
}
isErrorShown = true;
}
});

How to disable parent page of modal in angular

I have a modal window in Angular 4 that works fine but if the user clicks on the background / parent page the modal is closed.
I have found some solutions that suggest using backdrop='static' and keyboard=false when opening the modal but our modal uses a local Dialog class with a BehaviorSubject object so is opened using the .next method. I've also tried setting these attributes using div config but to no avail.
Therefore I'm looking for another solution, maybe using CSS or another setting / attribute that can be directly applied to the parent page or modal HTML.
See below for some of the relevant code.
dialog.component.ts:
constructor(private location: PlatformLocation,
private _dialog: DialogService,
private router: Router) { }
open() {
this.showDialog = true;
const body = document.body;
body.classList.add('cell-modal-open');
}
close() {
this.dialog = undefined;
}
private handleDialog(d: Dialog) {
if (!d) {
this.close();
} else if (d.template) {
if (this.showDialog) {
this.close();
}
this.dialog = d;
this.open();
}
}
ngOnInit() {
this.subscription = this
._dialog
.getDialog()
.subscribe({
next: (d) => { this.handleDialog(d); console.log('subscribed dialog') },
error: (err) => this.handleDialogError(err)
});
this.initialiseRoutingEventListeners();
}
dialog.service.ts
private d: Dialog = { template: null, size: DialogSizeEnum.XLarge };
private dialogSubject = new BehaviorSubject<Dialog>({ template: null, size: DialogSizeEnum.XLarge });
constructor() { }
showDialog(template: TemplateRef<any>, size = DialogSizeEnum.XLarge, requiresAction = false) {
Object.assign(this.d, { template: template, size: size, requiresAction: requiresAction });
if (this.d !== null) {
this.dialogSubject.next(this.d);
}
}
getDialog(): BehaviorSubject<Dialog> {
return this.dialogSubject;
}
clear() {
this.dialogSubject.next(null);
}
Any suggested approaches are welcome!
Added flag to the close() method and adding condition to only set to undefined if true (i.e. from a valid location).

Waiting till Meteor is connected using react-native-meteor

I'm using react-native-meteor to connect to Meteor server. When I run following code, I get the output as the screenshot. Connection doesn't established before the render method is called for the first time. How can I handle this? Can I block till the connection happens? ( onConnection method is not available in the react-native-meteor)
export default class App extends Component {
componentWillMount() {
console.log("GOing to connect");
Meteor.connect(SERVER_URL);
console.log("After connect : " + JSON.stringify(Meteor.status()));
}
render() {
console.log(Meteor.status());
console.log(JSON.stringify(Meteor.user()));
if (Meteor.status().status === "connected") {
if (Meteor.user()) {
return ( <
TestViewOne / >
);
} else {
return ( <
TestViewTwo / >
);
}
} else {
return ( < View > < /View>)
}
}
}
When I use the following code, the Meteor.user() still returns null.
Meteor.ddp.on('connected', function() {
console.log("on Connected : " + JSON.stringify(Meteor.user()));
localForceUpdate();
});
You need to set up the app to render a loading screen until the server is connected using withTracker, this way the main app will not progress to parts that assume the connection has been made:
class App extends Component {
constructor(props) {
super(props);
}
render() {
if (!this.appLaunched) {
if (!this.props.serverConnected || this.props.loggingIn) {
return <LoadingScreen />;
}
}
this.appLaunched = true; //this prevents the app reloading to front page everytime server reconnects
return (
<Root>
<AppContainer />
</Root>
);
}
}
export default withTracker(params => {
return {
loggingIn: Meteor.loggingIn(),
serverConnected: Meteor.status().connected
};
})(App);

render() method is not correctly called after props update

I'm doing a very simple react+redux application where I've a reducer called goals and a container called GoalsContainer.
From App Container I call the action goal for load the initial goals from a local db(indexedDB)
dispatch(loadGoals(currentDate));
This call the loadGoals from the goals actions:
export function loadGoals(currentDate = new Date()){
return dispatch => {
var goals = getGoalsFromDB(normalizeDate(currentDate)); // with this I get an array from the db
dispatch(setLoadGoals(goals));
}
}
function setLoadGoals(goals) {
return {
type: types.LOAD_GOALS,
goals
};
}
And then in my reducer I've this:
export default function goals(state = [], action) {
switch(action.type) {
case types.LOAD_GOALS:
return action.goals; // here I set the state of the goal reducer with the array passed via action
default:
console.log('Im here');
return state;
}
}
and this is my GoalsContainer(read the comments in code):
class GoalsContainer extends React.Component {
render() {
if (this.props.goals != undefined) {
console.log('ok called the render'); // in chrome console shows it
console.log(this.props.goals); // in chrome console shows correctly the goals loaded
console.log(this.props.goals.length); // it say 2
if (this.props.goals.length > 0) { // here fails...
console.log('good');
console.log(this.props.goals);
var goalsView = <div>There are goals</div>
}
else {
console.log('why go here?'); // go here
console.log(this.props.goals);
var goalsView = <div>No goals</div>
}
} else {
var goalsView = <div>Undefined</div>
}
return (
<div id="goals-main">
{goalsView}
</div>
);
}
}
GoalsContainer.propTypes = propTypes;
function mapStateToProps(state) {
const { goals, environment } = state;
const { currentDate } = environment;
return {
goals,
currentDate
}
}
export default connect(mapStateToProps)(GoalsContainer);
The problem is that when it does the if check, it fails(like if there are 0 goals), but in chrome console show correctly the goals array...
Then if I force with some workaround the render(), all works correctly.
What I've done wrong ?
You didn't mention if you use https://github.com/gaearon/redux-thunk or not. To use reducer returning function you should definitely install it.
It's hard to follow all of the parts of your code from random gists. What happens if you change your GoalsContainer to be;
class GoalsContainer extends React.Component {
render() {
console.log(this.props.goals);
return (
<div id="goals-main">
{(this.props.goals.length >= 1)?<div>There are goals</div>:<div>Nope!</div>}
</div>
);
}
}
What gets logged to the console?

extension appearing in the context menu of the browsers

I am developing a cross browser extension using kango framework. I want to add my extension to the context menu of the browser. I already have set "context_menu": true in the permissions array in extension_info.json file, but still my extension does not appear in the context menu ( when there is a right click in the browser window). How can I do this?
You need to add an event listener to main.js like this:
kango.ui.contextMenuItem.addEventListener(kango.ui.contextMenuItem.event.CLICK, function() {
kango.browser.tabs.getCurrent(function(tab) {
tab.dispatchMessage('ContextMenuItemClick');
});
});
And in the content.js you need to consume the event like this:
function handleContextMenuClick() {
var clickedElement = null;
if ('addEventListener' in document) {
document.addEventListener('mousedown', function(event) {
if (event.button == 2 && IsSupported()) {
clickedElement = event.target;
kango.console.log('StopIt menu item click 1');
}
}, true);
} else {
document.attachEvent('onmousedown', function(event) {
event = event || window.event;
if (event.button == 2&& IsSupported()) {
clickedElement = event.srcElement;
kango.console.log('StopIt menu item click 2');
}
});
}
kango.addMessageListener('ContextMenuItemClick', function(event) {
kango.console.log("addMessageListener: ContextMenuItemClick added");
});
}
handleContextMenuClick();
// Only activate the menu when the user is on facebook or twitter.
// This should be loaded from a service and updated one each new domain visited.
function IsSupported()
{
if(document.domain.indexOf("facebook.") > -1) return true;
if(document.domain.indexOf("twitter.") > -1) return true;
return false;
}

Resources