My terminal goes like this:
import { useEffect } from "react";
import { Terminal as TerminalType } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
//import { SearchAddon } from 'xterm-addon-search'
import 'xterm/css/xterm.css';
export const Terminal = ({
initialValue
} : {
initialValue?: string
}) => {
const id = 'xterm-container';
useEffect(() => {
const terminal = new TerminalType({
cursorBlink: true,
cursorStyle: window.api.isWindows ? "bar" : "underline"
});
const fitAddon = new FitAddon();
terminal.loadAddon(fitAddon);
window.api.receive('terminal.incomingData', (data) => {
terminal.write(data);
});
terminal.open(document.getElementById(id) as HTMLElement);
terminal.onData(key => {
window.api.send('terminal.keystroke', key);
});
terminal.focus();
window.api.send('terminal.keystroke', "cd C:\\\r\n");
}, []);
return (
<div id={id}></div>
)
}
where in the backend I connect xterm to real terminal like this:
ipcMain.on('terminal.keystroke', (_, key) => {
ptyProcess.write(key);
});
const shell = isWindows ? 'powershell.exe' : 'bash';
ptyProcess = spawn(shell, [], {
name: 'xterm-color',
cols: 80,
rows: 30,
cwd: isWindows ? process.env.USERPROFILE : process.env.HOME,
env: process.env as INonUndefinedEnv
});
ptyProcess.onData(data =>
EnforceNonNull(win).webContents.send('terminal.incomingData', data)
);
but when send the text, the cursor for some reason gets messed like in the below image. Sending a text like this reproduce the error:
window.api.send('terminal.keystroke', "cd C:\\\r\n");
By messed I mean this. cd is on top, then cd c:\ and the >> below PS. it's supposed to be something like this:
EDIT 2:
if i went to say type dir it goes like this:
EDIT 2: this seems to happen only in the very first line. After that, the curson position didn't seem to get messed anymore
Related
My async actions do not run correctly. Im new to Vue and JS and I am not sure what is happening here. I placed some confirm() dialogs within my code, to see which line passed and which not.
Within the ScanView.vue I call my addProduct action. I get the confirm dialog saying "addProduct" and dispatch calles the next callAPI action where I get the "callAPI" confirm dialog but nothing more. Seems like fetch() isnt working at all, because no any other dialog is shown. What am I doing wrong?
ScanView.vue
export default defineComponent({
name: "Home",
methods: {
scanEan() {
// QR Code Scanner Logic
this.$store.dispatch("addProduct", ean);
}
});
main.js
const store = new Vuex.Store({
state: {
products: [{
name: 'Produkt',
ean: '123',
amount: '1',
smallImageUrl: 'smImage',
mediumImageUrl: 'mdImage',
largeImageUrl: 'lgImage',
expiration: []
}]
},
mutations: {
addProduct(state, product) {
state.products.unshift(product);
}
},
actions: {
addProduct(context, ean) {
confirm("addProduct: " + ean);
context.dispatch('callAPI', ean);
},
callAPI(context, ean) {
confirm("callAPI: ");
fetch("https://world.openfoodfacts.org/api/v0/product/" + ean + ".json") //
.then(response => {
confirm("reesponse");
return response.json();
}
) //
.then(data => {
confirm("data: " + data);
context.dispatch('saveProduct', data);
});
},
saveProduct(context, data) {
confirm("saveProduct: ");
const name = data.product.product_name;
const ean = data.code;
const smImage = data.product.image_front_thumb_url;
const mdImage = data.product.image_front_small_url;
const lgImage = data.product.image_front_url;
const expiration = new Array();
const date = new Date(data.product.expiration_date);
expiration.push(date);
const product = new Product(
name,
ean,
smImage,
mdImage,
lgImage,
expiration
)
confirm("Produktdata: " + product);
context.commit('addProduct', product);
}
}
});
app.use(store);
EDIT
I build a simulate button for better testing. QR Scanning does not work in Browser.
Result It does work in Browser. But not on my emulator or android device. Seems like fetch() isnt the right way with ionic-vue. If I catch the error I got TypeError: Failed to fetch...
<template>
<button #click="simulateScan">Simulate Scan</button>
</template>
<script>
export default {
methods: {
simulateScan() {
this.$store.dispatch('addProduct', 737628064502);
}
}
};
</script>
Final Solution
fetch() does not work on android. You have to use something like cordova-http, capacitor-http, ionic-http or else. I used capacitorcommunity-http.
npm install #capacitor-community/http
npx cap sync
import { Http } from '#capacitor-community/http';
[...]
callAPI(context, ean) {
var eanurl = "https://world.openfoodfacts.org/api/v0/product/" + ean + ".json";
Http.get({ url: eanurl}) //
.then(response => {
return response.data;
}
) //
.then(data => {
console.log(data);
context.dispatch('saveProduct', data);
}).catch(error => confirm(error));
},
[...]
I am trying to build sub-pages for a projects category in Gatsby, each project parent page already generates the way it should but the sub-pages do not.
Each project can have zero to many sub-pages, I only want a sub-page to be generated if it exists. Data is coming from a headless CMS through GraphQL
My loop for generating these pages in gatsby-node.js currently looks like this:
result.data.allSanityProjects.edges.forEach(({ node }) => {
node.projectChildPages.map(childPage => {
if (node && node.projectChildPages.length > 0 && node.projectChildPages.slug) {
createPage({
path: childPage.slug + "/" + node.projectChildPages.slug,
component: projectsSubPages,
context: {
slug: childPage.slug + "/" + node.projectChildPages.slug,
},
});
}
});
});
});
This loops through the "allSanityProjects" part of this GrapQL query
{
allSanityDefaultPage {
edges {
node {
slug
}
}
}
allSanityProjects {
edges {
node {
slug
projectChildPages {
slug
}
}
}
}
}
The results of running just the allSanityProjects-query looks like this
{
"data": {
"allSanityProjects": {
"edges": [
{
"node": {
"slug": "project-3",
"projectChildPages": []
}
},
{
"node": {
"slug": "project-1",
"projectChildPages": [
{
"slug": "project-1"
},
{
"slug": "Doggolicious"
},
{
"slug": "no-cats"
}
]
}
},
{
"node": {
"slug": "Project-2",
"projectChildPages": []
}
}
]
}
}
}
Gatsby fails building the project child pages with the following error.
warn The GraphQL query in the non-page component
Exported queries are only executed for Page components. It's possible you're
trying to create pages in your gatsby-node.js and that's failing for some
reason.
If the failing component(s) is a regular component and not intended to be a page
component, you generally want to use a <StaticQuery> (https://gatsbyjs.org/docs/static-query)
instead of exporting a page query.
If you're more experienced with GraphQL, you can also export GraphQL
fragments from components and compose the fragments in the Page component
query and pass data down into the child component — https://graphql.org/learn/queries/#fragments
My template looks like this:
import React from "react";
import { useStaticQuery, graphql } from "gatsby";
import Layout from "../components/layout";
const BlockContent = require("#sanity/block-content-to-react");
const projectsSubPages = ({ data }) => {
const pageData = data.sanityProjects.projectChildPages;
return (
<Layout>
<BlockContent blocks={pageData._rawBlockContent} />
</Layout>
);
};
export const query = graphql`
query($slug: String!) {
sanityProjects(slug: { eq: $slug }) {
projectChildPages {
_rawBlockContent
slug
title
}
}
}
`;
export default projectsSubPages;
As far as I can tell my error is in my gatsby-node.js file, not in my template even though gatsby tells me my error is in my template. I've tried running the exact same templates as the others I use (just with different queries in them) and still get the same error.
My full gatsby-node.js file:
exports.createPages = ({ actions, graphql }) => {
const path = require(`path`);
const { createPage } = actions;
const projects = path.resolve("src/templates/projects.js");
const defaultPage = path.resolve("src/templates/defaultPage.js");
const projectsSubPages = path.resolve("src/templates/projectsSubPages.js");
return graphql(`
{
allSanityDefaultPage {
edges {
node {
slug
}
}
}
allSanityProjects {
edges {
node {
slug
projectChildPages {
slug
}
}
}
}
}
`).then((result) => {
if (result.errors) {
reporter.panic("failed to create pages ", result.errors);
}
result.data.allSanityDefaultPage.edges.forEach(({ node }) => {
createPage({
path: node.slug,
component: defaultPage,
context: {
slug: node.slug,
},
});
});
result.data.allSanityProjects.edges.forEach(({ node }) => {
createPage({
path: node.slug,
component: projects,
context: {
slug: node.slug,
},
});
});
result.data.allSanityProjects.edges.forEach(({ node }) => {
node.projectChildPages.map(childPage => {
if (node && node.projectChildPages.length > 0 && node.projectChildPages.slug) {
createPage({
path: childPage.slug + "/" + node.projectChildPages.slug,
component: projectsSubPages,
context: {
slug: childPage.slug + "/" + node.projectChildPages.slug,
},
});
}
});
});
});
};
code
result.data.allSanityProjects.edges.forEach(({ node }) => {
node.projectChildPages.map(childPage => {
if (node && node.projectChildPages.length > 0 && node.projectChildPages.slug) {
Condition doesn't have much sense there:
if you're in .map() then for sure node and node.projectChildPages.length > 0 are true
projectChildPages is an array so no projectChildPages.slug here
query
Your fetched data (source) doesn't contain _rawBlockContent so you can't query for this in page component.
I am new to Vuex and Nuxt.
I would like to use vuex to fetch dropbox filestructure and store them.
Here is my code. the console.log seems to work fine. it prints out something like below.
But the structure still turns out to be [] when i use in index.vue
[ { '.tag': 'file',
name: 'Document.docx',
path_lower: '/posts/document.docx',
path_display: '/posts/Document.docx',
id: 'id:H_6Dhj1r7cEAAAAAAAAXlQ',
client_modified: '2018-09-02T14:23:05Z',
server_modified: '2018-09-02T14:23:06Z',
rev: '5e5cab150',
size: 11366,
content_hash: 'd26bb0382752820694d31f42e82e31ef72bed683b90e02952ea09125264d4124' },
{ '.tag': 'file',
name: '2013-5-17-first-post.md',
path_lower: '/posts/2013-5-17-first-post.md',
path_display: '/posts/2013-5-17-first-post.md',
id: 'id:H_6Dhj1r7cEAAAAAAAAXlg',
client_modified: '2018-09-02T14:25:38Z',
server_modified: '2018-09-02T14:25:38Z',
rev: '6e5cab150',
size: 136,
content_hash: '3b8d60de425e8280d55e45d7359cd3290abc5bc3b0bb6831b09a6da0d3cb6a12' } ]
the code is like below
import "isomorphic-fetch"
import {
Dropbox
} from "dropbox";
import {
DropboxTeam
} from "dropbox";
export const state = () => ({
structure: []
});
export const mutations = {
setStucture(state, structure) {
state.structure = structure.slice();
console.log(state.structure);
// console.log(structure.slice());
}
};
export const actions = {
async nuxtServerInit({ commit }) {
let accessToken = "XXXXX"
let dropbox = new Dropbox({
accessToken: accessToken
});
dropbox.filesListFolder({path: '/posts'})
.then(response => {
const structure = response.entries;
commit("setStucture", structure);
})
.catch(error => {
console.log(error);
});
}
};
Can I get some help. Thank you!
add await to dropbox.filesListFolder({path: '/posts'}) like below turned out to be the right answer.
await dropbox.filesListFolder({path: '/posts'})
I'm developing an Electron application and I aim to 'split up' index.js (main process) file. Currently I have put my menu bar-related and Touch Bar-related code into two separate files, menu.js and touchBar.js. Both of these files rely on a function named redir, which is in index.js. Whenever I attempt to activate the click event in my Menu Bar - which relies on redir - I get an error:
TypeError: redir is not a function. This also applies to my Touch Bar code.
Here are my (truncated) files:
index.js
const { app, BrowserWindow } = require('electron'); // eslint-disable-line
const initTB = require('./touchBar.js');
const initMenu = require('./menu.js');
...
let mainWindow; // eslint-disable-line
// Routing + IPC
const redir = (route) => {
if (mainWindow.webContents) {
mainWindow.webContents.send('redir', route);
}
};
module.exports.redir = redir;
function createWindow() {
mainWindow = new BrowserWindow({
height: 600,
width: 800,
title: 'Braindead',
titleBarStyle: 'hiddenInset',
show: false,
resizable: false,
maximizable: false,
});
mainWindow.loadURL(winURL);
initMenu();
mainWindow.setTouchBar(initTB);
...
}
app.on('ready', createWindow);
...
menu.js
const redir = require('./index');
const { app, Menu, shell } = require('electron'); // eslint-disable-line
// Generate template
function getMenuTemplate() {
const template = [
...
{
label: 'Help',
role: 'help',
submenu: [
{
label: 'Learn more about x',
click: () => {
shell.openExternal('x'); // these DO work.
},
},
...
],
},
];
if (process.platform === 'darwin') {
template.unshift({
label: 'Braindead',
submenu: [
...
{
label: 'Preferences...',
accelerator: 'Cmd+,',
click: () => {
redir('/preferences'); // this does NOT work
},
}
...
],
});
...
};
return template;
}
// Set the menu
module.exports = function initMenu() {
const menu = Menu.buildFromTemplate(getMenuTemplate());
Menu.setApplicationMenu(menu);
};
My file structure is simple - all three files are in the same directory.
Any code criticisms are also welcome; I've spent hours banging my head trying to figure all this out.
redir it is not a function, because you're exporting an object, containing a redir property, which is a function.
So you should either use:
const { redir } = require('./index.js');
Or export it this way
module.exports = redir
When you do: module.exports.redir = redir;
You're exporting: { redir: [Function] }
You are exporting
module.exports.redir = redir;
That means that your import
const redir = require('./index');
is the exported object. redir happens to be one of its keys. To use the function, use
const redir = require('./index').redir;
or destructure directly into redir
const { redir } = require('./index');
I am trying to create a Todos example app using the generator-react-webpack from here. Everything works until I started using alt for the flux pattern. When I run the project using npm run, I got the following error:
TodoStore.js: Unexpected token (12:0)
10 | import _ from 'lodash';
11 |
12 | #datasource(CategorySource)
It complains about the line 12 above for the #datasource decorator. Below is the code from my TodoStore.js:
'use strict';
const alt = require('../alt');
const Actions = require('../actions');
import {decorate, bind, datasource} from 'alt/utils/decorators';
import CategorySource from '../sources/CategorySource';
import _ from 'lodash';
#datasource(CategorySource)
#decorate(alt)
class TodoStore {
constructor() {
this.state = {
user: null,
todos: null,
todosLoading: true
};
}
#bind(Actions.todosLoading)
todosLoading() {
this.setState({
todosLoading: true
});
}
#bind(Actions.todosReceived)
receivedTodos(todos) {
_(todos)
.keys()
.each((k) => {
todos[k].key = k;
})
.value();
this.setState({todos, todosLoading: false});
}
#bind(Actions.categoriesReceived)
receivedCategories(categories) {
let selectedCategory;
_(categories)
.keys()
.each((key, index) => {
categories[key].key = key;
if (index == 0) {
categories[key].selected = true;
selectedCategory = categories[key];
}
})
.value();
this.setState({categories, selectedCategory, todosDirty: true});
}
#bind(Actions.login)
login(user) {
this.setState({user: user});
}
}
export default alt.createStore(TodoStore);
I found this post for a similar problem, but I don't have any luck getting it to work by changing this line: test: /\.jsx?$/, in my webpack.config.js file.
found out the reason: because it does not recognize the ES7 decorator syntax. I created a file named .babelrc at the root and its content is:
{
"stage": 0
}
Now everything works! Hope this will help someone in the future.