kasy-cli 1.26.0 → 1.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/commands/new.js
CHANGED
|
@@ -205,16 +205,17 @@ async function confirmIdentities(backend, gcloudAccount, tr, cancel) {
|
|
|
205
205
|
* id elsewhere). Never throws.
|
|
206
206
|
*/
|
|
207
207
|
async function ensureGcloudReady(tr) {
|
|
208
|
-
const { spawnSync } = require('node:child_process');
|
|
208
|
+
const { spawnSync, exec } = require('node:child_process');
|
|
209
209
|
const { augmentedEnv } = require('../utils/env-tools');
|
|
210
210
|
|
|
211
211
|
let check = await checkGcloudAuth();
|
|
212
212
|
if (check.ok) return check;
|
|
213
213
|
|
|
214
|
-
// 1) Not installed → offer to install it
|
|
214
|
+
// 1) Not installed → tell the user it's missing, then offer to install it.
|
|
215
215
|
if (check.missing === 'gcloud') {
|
|
216
216
|
const guide = getGcloudInstallInstructions();
|
|
217
217
|
if (guide.install) {
|
|
218
|
+
ui.log.warn(tr('new.firebase.create.gcloudMissing'));
|
|
218
219
|
const doInstall = await ui.confirm({
|
|
219
220
|
message: tr('new.firebase.create.gcloudInstallConfirm'),
|
|
220
221
|
initialValue: true,
|
|
@@ -222,11 +223,20 @@ async function ensureGcloudReady(tr) {
|
|
|
222
223
|
if (doInstall) {
|
|
223
224
|
const spinner = ui.timedSpinner();
|
|
224
225
|
spinner.start(tr('new.firebase.create.gcloudInstalling'));
|
|
225
|
-
|
|
226
|
+
// Run async (NOT spawnSync): a synchronous child blocks the event loop,
|
|
227
|
+
// which freezes the spinner — the user stares at a dead screen for
|
|
228
|
+
// minutes. exec keeps the clock ticking so it's clear it's working.
|
|
229
|
+
await new Promise((resolve) => {
|
|
230
|
+
exec(
|
|
231
|
+
guide.install,
|
|
232
|
+
{ env: augmentedEnv(), timeout: 600_000, windowsHide: true, maxBuffer: 50 * 1024 * 1024 },
|
|
233
|
+
() => resolve()
|
|
234
|
+
);
|
|
235
|
+
});
|
|
226
236
|
spinner.stop(tr('new.firebase.create.gcloudInstalling'));
|
|
227
|
-
// checkGcloudAuth
|
|
228
|
-
// process PATH, which doesn't see a tool winget just
|
|
229
|
-
//
|
|
237
|
+
// checkGcloudAuth and the later billing/project calls use the plain
|
|
238
|
+
// process PATH, which doesn't see a tool winget just put on the machine
|
|
239
|
+
// PATH. Inject the known gcloud dir so the rest of the flow works.
|
|
230
240
|
const env = augmentedEnv();
|
|
231
241
|
if (env.PATH) process.env.PATH = env.PATH;
|
|
232
242
|
if (process.platform === 'win32' && env.Path) process.env.Path = env.Path;
|
|
@@ -238,6 +238,7 @@ module.exports = {
|
|
|
238
238
|
'new.firebase.create.installAfter': 'Then log in',
|
|
239
239
|
'new.firebase.create.installUrl': 'Or download from',
|
|
240
240
|
'new.firebase.create.authCommand': 'Run: gcloud auth login',
|
|
241
|
+
'new.firebase.create.gcloudMissing': 'The Google Cloud CLI (gcloud) is required to create the Firebase project from scratch, and it is not installed yet.',
|
|
241
242
|
'new.firebase.create.gcloudInstallConfirm': 'Install the Google Cloud CLI (gcloud) automatically now?',
|
|
242
243
|
'new.firebase.create.gcloudInstalling': 'Installing the Google Cloud CLI…',
|
|
243
244
|
'new.firebase.create.gcloudAuthOpening': 'Opening the Google sign-in in your browser — log in with your account…',
|
|
@@ -238,6 +238,7 @@ module.exports = {
|
|
|
238
238
|
'new.firebase.create.installAfter': 'Luego inicia sesión',
|
|
239
239
|
'new.firebase.create.installUrl': 'O descarga en',
|
|
240
240
|
'new.firebase.create.authCommand': 'Ejecuta: gcloud auth login',
|
|
241
|
+
'new.firebase.create.gcloudMissing': 'El Google Cloud CLI (gcloud) es necesario para crear el proyecto Firebase desde cero, y aún no está instalado.',
|
|
241
242
|
'new.firebase.create.gcloudInstallConfirm': '¿Instalar el Google Cloud CLI (gcloud) automáticamente ahora?',
|
|
242
243
|
'new.firebase.create.gcloudInstalling': 'Instalando el Google Cloud CLI…',
|
|
243
244
|
'new.firebase.create.gcloudAuthOpening': 'Abriendo el inicio de sesión de Google en el navegador — entra con tu cuenta…',
|
|
@@ -238,6 +238,7 @@ module.exports = {
|
|
|
238
238
|
'new.firebase.create.installAfter': 'Depois faca login',
|
|
239
239
|
'new.firebase.create.installUrl': 'Ou baixe em',
|
|
240
240
|
'new.firebase.create.authCommand': 'Execute: gcloud auth login',
|
|
241
|
+
'new.firebase.create.gcloudMissing': 'O Google Cloud CLI (gcloud) é necessário para criar o projeto Firebase do zero, e ainda não está instalado.',
|
|
241
242
|
'new.firebase.create.gcloudInstallConfirm': 'Instalar o Google Cloud CLI (gcloud) automaticamente agora?',
|
|
242
243
|
'new.firebase.create.gcloudInstalling': 'Instalando o Google Cloud CLI…',
|
|
243
244
|
'new.firebase.create.gcloudAuthOpening': 'Abrindo o login do Google no navegador — entre com a sua conta…',
|
package/package.json
CHANGED
|
@@ -227,28 +227,24 @@ class _FocusableSidebarState extends State<_FocusableSidebar> {
|
|
|
227
227
|
|
|
228
228
|
@override
|
|
229
229
|
Widget build(BuildContext context) {
|
|
230
|
-
//
|
|
231
|
-
//
|
|
232
|
-
//
|
|
233
|
-
//
|
|
230
|
+
// Reading-order group (NOT an ordered policy): this is the exact structure
|
|
231
|
+
// that made the anchor hold the initial focus. The anchor sits at (0,0) and
|
|
232
|
+
// is skipped by Tab; the skip link is positioned at the very top, so reading
|
|
233
|
+
// order makes it the FIRST Tab stop, then the sidebar items, then (via the
|
|
234
|
+
// scaffold) the header and content. Swapping in an OrderedTraversalPolicy
|
|
235
|
+
// here broke the anchor, so we keep reading order and rely on position.
|
|
234
236
|
return FocusTraversalGroup(
|
|
235
|
-
policy: OrderedTraversalPolicy(),
|
|
236
237
|
child: Stack(
|
|
237
238
|
clipBehavior: Clip.none,
|
|
238
239
|
children: [
|
|
239
|
-
|
|
240
|
-
order: const NumericFocusOrder(1),
|
|
241
|
-
child: FocusTraversalGroup(child: widget.child),
|
|
242
|
-
),
|
|
240
|
+
widget.child,
|
|
243
241
|
// Zero-size sibling; only holds the initial keyboard focus.
|
|
244
242
|
Focus(focusNode: _anchor, child: const SizedBox.shrink()),
|
|
243
|
+
// Topmost on screen, so reading order makes it the first Tab stop.
|
|
245
244
|
Positioned(
|
|
246
245
|
top: KasySpacing.sm,
|
|
247
246
|
left: KasySpacing.sm,
|
|
248
|
-
child:
|
|
249
|
-
order: const NumericFocusOrder(0),
|
|
250
|
-
child: _SkipToContentLink(onSkip: _skipToContent),
|
|
251
|
-
),
|
|
247
|
+
child: _SkipToContentLink(onSkip: _skipToContent),
|
|
252
248
|
),
|
|
253
249
|
],
|
|
254
250
|
),
|