Identify orientation with degrees on startup - react-native

Without a 3rd party lib, we can detect orientation changes with DeviceEventEmitter with this undocumented feature like this:
import { DeviceEventEmitter } from 'react-native'
function handleOrientationDidChange(data) {
console.log('orientation changed, data:', data)
}
DeviceEventEmitter.addListener('namedOrientationDidChange', handleOrientationDidChange);
This gives us data that looks like this:
{ rotationDegrees: -90, isLandscape: true, name: "landscape-primary" }
Note: I tested this only on Android. It would be nice to know if it works on iOS too.
However this only works ON CHANGE. Is there a way to get this info on startup?

Have you tried this library!
Here is example usage from the repo:
componentWillMount() {
// The getOrientation method is async. It happens sometimes that
// you need the orientation at the moment the JS runtime starts running on device.
// `getInitialOrientation` returns directly because its a constant set at the
// beginning of the JS runtime.
const initial = Orientation.getInitialOrientation();
if (initial === 'PORTRAIT') {
// do something
} else {
// do something else
}
}

Related

CKEditor5-Vue autosave problem. I can't call instance in autosave function

The editor work fine except autosave.
I import autosave plugin properly,and I can receive the return data.
https://i.stack.imgur.com/cDW9x.jpg
in this case, i can receive the autosave data.
But I can't call Vue instance inside the autosave function.
https://i.stack.imgur.com/5Nyq4.jpg
https://i.stack.imgur.com/sevjo.jpg
I can't call my vue instance by 'this',that means i can't use methods,vuex store...and so on.
How can i fix hti?
I know this is a bit late but for anyone (like myself) looking for an answer to this I followed the advice in this [SO link][1]
data() {
var self = this
...
return {
editorConfig: {
autosave: {
waitingTime: 3000, // in ms
save(editor) {
self.saveData(editor.getData())
}
},
}
}
}
[1]: https://stackoverflow.com/a/61509032/558720

Add CoreUI icon to DevExtreme dxDataGrid column header in Vue.js

Currently I am working on a new UI for a legacy API. Unfortunately, this one delivers HTML source code for a column header. This code usually creates a FontAwesome icon. This library will not be used in the new project.
I found a very similar icon in the Icon Library of CoreUI. Now it is only a matter of rendering the icon at this point. However, no approach has been successful so far. How can I replace the icon in the headerCellTemplate method?
Or maybe there is a completely different, much better approach to do this. I don't know if I am on the right track with this method approach. You can probably use static templates, but I don't know how to do that.
import { CIcon } from '#coreui/vue';
import { cilCheckCircle } from '#coreui/icons';
headerCellTemplate: (element, info) => {
element.innerHTML = curr.ColumnTitle;
if (element.firstChild.nodeName === 'I') {
// WORKS
//element.firstChild.innerHTML = 'Done';
// ANOTHER EXPERIMENT
//const componentClass = Vue.extend(cilCheckCircle);
//const instance = new componentClass();
//instance.$mount();
//element.removeChild(element.firstChild);
//element.appendChild(instance.$el);
// ALSO NOT WORKING
return CIcon.render.call(this, cilCheckCircle);
}
}
I finally found a solution after revisiting this interesting article.
import Vue from 'vue';
import { CIcon } from '#coreui/vue';
import { cilCheckCircle } from '#coreui/icons';
headerCellTemplate: (element, info) => {
element.innerHTML = curr.ColumnTitle;
if (element.firstChild.nodeName === 'I') {
const cIconClass = Vue.extend(CIcon);
const instance = new cIconClass({
propsData: { content: cilCheckCircle }
});
instance.$mount(element.firstChild);
}
}
I don't know, though, if this is the ideal solution. So feel free to tell me, if you have a better, less complex solution.

Is it possible to use metadata inside the test script?

Is there a way to do an IF condition on the metadata in the test script? For e.g
test.meta({ tablet: ‘true’, portrait: 'false', landscape: 'true' })(‘L0 | Tablet device’, async t => {
// Verify component exists in portrait and landscape mode
await t.expect(abc).ok();
// Verify component exists in landscape mode only
if (t.metadata.landscape == 'true') {
......
}
});
You can get the meta inside a test using the following code:
t.testRun.test.meta
However, I need to note that it's not a documented API, and it can be changed in the future, so you need to use it carefully.
I think in your case, the best solution will be something like this:
const isTablet = true;
test.meta({ tablet: isTablet })(‘L0 | Tablet device’, async t => {
if (isTablet) {
......
}
});

ReactJS - app functions in different files

I'm trying to make React-based web game. I have an App component which holds pretty much all non-UX state. To avoid code duplication I also hold most functions in it and pass it down as prop to child components.
But now I'm starting to get cluttered by different functions, all in the App body. Is there any simple way to satisfactory structure this in different files? Should I already look into state management libraries?
Currently stuff looks like:
class App extends Component {
constructor(props) {
super(props);
this.state = gameInitialize();
this.modifyState = this.modifyState.bind(this);
this.moveUnit = this.moveUnit.bind(this);
this.progressMission = this.progressMission.bind(this);
this.timeJump = this.timeJump.bind(this);
this.competenceAfterTimeJump = this.competenceAfterTimeJump.bind(this);
this.save = this.save.bind(this);
this.load = this.load.bind(this);
}
componentDidMount() {
this.timerID = setInterval(this.modifyState, this.state.interval);
window.addEventListener('beforeunload', this.save);
this.load();
}
componentWillUnmount() {
clearInterval(this.timerID);
}
save() {
localStorage.setItem("gameSave", toJson(this.state));
}
load() {
let state = 0;
try {
state = fromJson(localStorage.getItem("gameSave"));
} catch (error) {
console.log(error);
return 0;
}
state.units.map(unit => {
delete unit.__parent;
delete unit.attributes.__parent
return 0;
});
state.missions.map(mission => delete mission.__parent);
this.setState(state);
}
modifyState() {
this.setState(this.state.units.map(this.progressMission));
this.setState(this.state);
}
progressMission(unit) {
const mission = unit.currentMission;
let increment = unit.attributes[mission.type].total() - mission.complexity;
if (increment < 0) increment = 0;
mission.progress += increment * this.state.interval / 1000 * unit.competence / 10;
if (mission.progress >= mission.difficulty) {
mission.progress = 0;
this.state.experience.get(mission.reward);
mission.completions += 1;
}
}
moveUnit(unit, mission) {
unit.currentMission = mission;
this.setState(this.state);
}
timeJump() {
const game = this.state;
while (game.units.length > 2) {
game.units.pop();
};
game.units.map(function (unit) {
Object.keys(unit.attributes).map((key) => { unit.attributes[key] = newAttribute() });
unit.currentMission = game.missions[0];
});
game.missions.map((mission) => {mission.progress = 0});
game.units[0].competence = this.competenceAfterTimeJump();
game.experience.current = 0;
this.setState(game);
}
competenceAfterTimeJump() {
return (10 + Math.sqrt(this.state.experience.total) / 10);
}
render() {
return (
<div className="App">
<header className="App-header">
<h1 className="title">Time-traveling Hero: eventually I'll save the world, or maybe not if I don't feel it</h1>
</header>
<SaveLoad game={this} />
<Prestige game={this} />
<MissionWrapper>
<MissionList missions={this.state.missions} game={this} />
</MissionWrapper>
<UnitWrapper>
<ExpWrapper>
<div>
Available Experience: {this.state.experience.current.toFixed(1)}
</div>
<div>
Total Experience: {this.state.experience.total.toFixed(1)}
</div>
</ExpWrapper>
<UnitList units={this.state.units} game={this} />
</UnitWrapper>
</div>
);
}
}
function gameInitialize() {
let game = { units: [], missions: [], currentUnit: undefined };
game.interval = 10;
game.missions = generateMissions(50);
game.experience = {
current: 0, total: 0,
get: function (amount) { this.current += amount; this.total += amount },
spend: function (amount) {
if (this.current >= amount) {
this.current -= amount;
return true;
}
else return false;
}
};
game.units.push({ name: "Hero", attributes: newAttributes(), competence: 10, currentMission: game.missions[0] });
game.units.push({ name: "Childhood Friend", attributes: newAttributes(), competence: 15, currentMission: game.missions[0] });
game.currentUnit = game.units[0];
game.missionsWithUnits = function () {
this.missions.map()
}
return game;
}
How should I proceed?
Yes, it's super easy to organize JS code! Use modules. Here's how to do it.
Export functions from a file
adders.js:
export function addTwo (number) {
return number + 2
}
Then use it:
This could be in a component file:
import { addTwo } from './path/to/adders.js'
console.log(addTwo(5)) // logs 7
You can organize this super well for a lot of things. If you have a group of related functions, use a module like this. here's the file structure:
mathStuff/
adders.js
index.js
You have all of your related files in the same folder and your functions exported from the individual files like above. Then set up index like this:
index.js:
import * as adders from './adders.js'
// Set up your object however you want.
const MathStuff = {
...adders
}
export default MathStuff
Then in any component you can do this:
import MathStuff from './path/to/mathStuff'
MathStuff.addTwo(7) // 9
For even more organization, you could set your index up to have functions like this:
index.js:
import * as adders from './adders.js'
import * as dividers from './dividers.js' // another math file with division functions or something
// Set up your object however you want.
const MathStuff = {
adders,
dividers
}
export default MathStuff
And use it like this:
import MathStuff from './path/to/mathStuff' // points to directory, NOT individual file
MathStuff.adders.addTwo(7) // 9
I would definitely suggest organizing code like this. One thing this improves is testability - it's very easy to test pure functions with no side effects.
I like to put my database code in one module and import it wherever to access all my database functions.
I like to put all of my business logic in different modules by category - for instance GameLogic or something like that.
This will also help you write more functional code. Currently, you have a lot of state modification within individual functions - you won't be able to do that in modules without binding individual functions to the this context of your react component. Instead, I would suggest passing all necessary parameters to the function and having it return a value. This moves business logic away, making it easier to manage state.
For instance, your progressMission function accesses this.state.interval. You can pass interval to the function itself.
One thing I'm noticing is that your code has a lot of dependency on each other - functions often have to access lots of things outside of itself, rather than being self-contained. It would probably help you a lot to try to refactor into a modular system, where functions are much more pure - only accessing what is passed to them, and returning values which get used. Using actual modules like above definitely helps do that - my code got better the more I did it. It helps you reason about your code better. Additionally, once/if you start implementing tests, you'll find that all of the tangled-ness of the code makes it hard to test - there are a lot of side effects.
Finally, redux and external state management probably won't help a ton in your case, but they might. Redux can help you achieve state that's easier to reason about, but it won't help you organize code better per se. I hope that helps!

Detecting browser print event

Is it possible to detect when a user is printing something from their browser?
To complicate matters, if we are presenting a user with a PDF document in a new window is it possible to detect the printing of that document ( assuming the user prints it from the browser window)?
The closest I've been able to find is if we implement custom print functionality (something like this) and track when that is invoked
I'm primarily interested in a solution that works for internet explorer (6 or later)
You can now detect a print request in IE 5+, Firefox 6+, Chrome 9+, and Safari 5+ using the following technique:
(function() {
var beforePrint = function() {
console.log('Functionality to run before printing.');
};
var afterPrint = function() {
console.log('Functionality to run after printing');
};
if (window.matchMedia) {
var mediaQueryList = window.matchMedia('print');
mediaQueryList.addListener(function(mql) {
if (mql.matches) {
beforePrint();
} else {
afterPrint();
}
});
}
window.onbeforeprint = beforePrint;
window.onafterprint = afterPrint;
}());
I go into more detail into what this is doing and what it can be used for at http://tjvantoll.com/2012/06/15/detecting-print-requests-with-javascript/.
For Internet Exploder, there are the events window.onbeforeprint and window.onafterprint but they don't work with any other browser and as a result they are usually useless.
They seem to work exactly the same for some reason, both executing their event handlers before the printing window opens.
But in case you want it anyway despite these caveats, here's an example:
window.onbeforeprint = function() {
alert("Printing shall commence!");
}
For anyone reading this on 2020.
The addListener function is mostly deprecated in favor of addEventListener except for Safari:
if (window.matchMedia) {
const media = window.matchMedia("print");
const myFunc = mediaQueryList => {
if (mediaQueryList.matches) {
doStuff();
}
};
try {
media.addEventListener("change", myFunc);
} catch (error) {
try {
media.addListener(myFunc);
} catch (error) {
console.debug('Error', error)
}
}
}
Reference: This other S.O question
If it's only for tracking purposes, perhaps you could set a background url in CSS print media to a server page (.aspx, .php, etc) and then do something on the server?
This guy claims it works.
This is not as versitile as TJ's solution, but it may be less buggy (see TJs blog post for issues he found) when only tracking is needed.