Commit Graph

28 Commits

Author SHA1 Message Date
Ryan Rehman 73fac8e1d7 toggler: Allow skipping over disabled tabs.
This commit allows skipping over any disabled tabs
that are in the middle when using the left or right
arrow keys.

We also add `enable_tab` to the `components` API.
2020-08-04 15:48:34 -07:00
Anders Kaseorg 6ec808b8df js: Add "use strict" directive to CommonJS files.
ES and TypeScript modules are strict by default and don’t need this
directive.  ESLint will remind us to add it to new CommonJS files and
remove it from ES and TypeScript modules.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-07-31 22:09:46 -07:00
Anders Kaseorg d2520cd7e0 js: Replace underscore with lodash and remove it from globals.
Tweaked by tabbott to bump PROVISION_VERSION.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-07-26 16:12:06 -07:00
Anders Kaseorg 96dcc0ce6e js: Use ES6 object literal shorthand syntax.
Generated by ESLint.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-07-21 12:42:22 -07:00
Anders Kaseorg a9ca5f603b js: Replace deprecated jQuery event trigger shorthand.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-07-21 12:01:26 -07:00
Anders Kaseorg 4e42137bd9 js: Replace deprecated jQuery event handler shorthand.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-07-21 12:01:26 -07:00
Anders Kaseorg b65d2e063d js: Reformat with Prettier.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-07-17 14:31:25 -07:00
Anders Kaseorg 883e2fd325 js: Remove inner spacing from object literals.
We’re configuring Prettier with bracketSpacing: false.  Generated by
ESLint.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-07-17 14:31:25 -07:00
Anders Kaseorg a20c12366f js: Use inside variant of IIFE wrappers.
Prettier would do this anyway, but it’s separated out for a more
reviewable diff.  Generated by ESLint.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-07-17 14:31:25 -07:00
Anders Kaseorg f3726db89a js: Normalize strings to double quotes.
Prettier would do this anyway, but it’s separated out for a more
reviewable diff.  Generated by ESLint.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-07-17 14:31:24 -07:00
Anders Kaseorg a79322bc94 eslint: Enable prefer-arrow-callback.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-07-03 16:55:50 -07:00
vaibhavrajsingh2001 2c0c936e40 stream settings: Correct alignment of filter streams div.
The div containing options for filtering streams was placed in the
centre. Aligned it towards the right. Had to pass a special check
variable in subs.js:540 to add the specific class for this purpose.
This was a specific scenario where this sort of CSS was to be added,
hence had to make a specific case.

Also, fixed the bottom border color of the search streams bar for night
mode.
2020-04-21 16:59:41 -07:00
Steve Howell b994889315 node tests: Just set i18n every time.
Explicitly stubbing i18n in 48 different files
is mostly busy work at this point, and it doesn't
provide much signal, since often it's invoked
only to satisfy transitive dependencies.
2020-02-28 17:11:24 -08:00
Anders Kaseorg 02511bff1c js: Automatically convert _.each to for…of.
This commit was automatically generated by the following script,
followed by lint --fix and a few small manual lint-related cleanups.

import * as babelParser from "recast/parsers/babel";
import * as recast from "recast";
import * as tsParser from "recast/parsers/typescript";
import { builders as b, namedTypes as n } from "ast-types";
import { Context } from "ast-types/lib/path-visitor";
import K from "ast-types/gen/kinds";
import { NodePath } from "ast-types/lib/node-path";
import assert from "assert";
import fs from "fs";
import path from "path";
import process from "process";

const checkExpression = (node: n.Node): node is K.ExpressionKind =>
  n.Expression.check(node);
const checkStatement = (node: n.Node): node is K.StatementKind =>
  n.Statement.check(node);

for (const file of process.argv.slice(2)) {
  console.log("Parsing", file);
  const ast = recast.parse(fs.readFileSync(file, { encoding: "utf8" }), {
    parser: path.extname(file) === ".ts" ? tsParser : babelParser,
  });
  let changed = false;
  let inLoop = false;
  let replaceReturn = false;

  const visitLoop = (...args: string[]) =>
    function(this: Context, path: NodePath) {
      for (const arg of args) {
        this.visit(path.get(arg));
      }
      const old = { inLoop };
      inLoop = true;
      this.visit(path.get("body"));
      inLoop = old.inLoop;
      return false;
    };

  recast.visit(ast, {
    visitDoWhileStatement: visitLoop("test"),

    visitExpressionStatement(path) {
      const { expression, comments } = path.node;
      let valueOnly;
      if (
        n.CallExpression.check(expression) &&
        n.MemberExpression.check(expression.callee) &&
        !expression.callee.computed &&
        n.Identifier.check(expression.callee.object) &&
        expression.callee.object.name === "_" &&
        n.Identifier.check(expression.callee.property) &&
        ["each", "forEach"].includes(expression.callee.property.name) &&
        [2, 3].includes(expression.arguments.length) &&
        checkExpression(expression.arguments[0]) &&
        (n.FunctionExpression.check(expression.arguments[1]) ||
          n.ArrowFunctionExpression.check(expression.arguments[1])) &&
        [1, 2].includes(expression.arguments[1].params.length) &&
        n.Identifier.check(expression.arguments[1].params[0]) &&
        ((valueOnly = expression.arguments[1].params[1] === undefined) ||
          n.Identifier.check(expression.arguments[1].params[1])) &&
        (expression.arguments[2] === undefined ||
          n.ThisExpression.check(expression.arguments[2]))
      ) {
        const old = { inLoop, replaceReturn };
        inLoop = false;
        replaceReturn = true;
        this.visit(
          path
            .get("expression")
            .get("arguments")
            .get(1)
            .get("body")
        );
        inLoop = old.inLoop;
        replaceReturn = old.replaceReturn;

        const [right, { body, params }] = expression.arguments;
        const loop = b.forOfStatement(
          b.variableDeclaration("let", [
            b.variableDeclarator(
              valueOnly ? params[0] : b.arrayPattern([params[1], params[0]])
            ),
          ]),
          valueOnly
            ? right
            : b.callExpression(
                b.memberExpression(right, b.identifier("entries")),
                []
              ),
          checkStatement(body) ? body : b.expressionStatement(body)
        );
        loop.comments = comments;
        path.replace(loop);
        changed = true;
      }
      this.traverse(path);
    },

    visitForStatement: visitLoop("init", "test", "update"),

    visitForInStatement: visitLoop("left", "right"),

    visitForOfStatement: visitLoop("left", "right"),

    visitFunction(path) {
      this.visit(path.get("params"));
      const old = { replaceReturn };
      replaceReturn = false;
      this.visit(path.get("body"));
      replaceReturn = old.replaceReturn;
      return false;
    },

    visitReturnStatement(path) {
      if (replaceReturn) {
        assert(!inLoop); // could use labeled continue if this ever fires
        const { argument, comments } = path.node;
        if (argument === null) {
          const s = b.continueStatement();
          s.comments = comments;
          path.replace(s);
        } else {
          const s = b.expressionStatement(argument);
          s.comments = comments;
          path.replace(s, b.continueStatement());
        }
        return false;
      }
      this.traverse(path);
    },

    visitWhileStatement: visitLoop("test"),
  });

  if (changed) {
    console.log("Writing", file);
    fs.writeFileSync(file, recast.print(ast).code, { encoding: "utf8" });
  }
}

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-07 14:09:47 -08:00
Anders Kaseorg 28f3dfa284 js: Automatically convert var to let and const in most files.
This commit was originally automatically generated using `tools/lint
--only=eslint --fix`.  It was then modified by tabbott to contain only
changes to a set of files that are unlikely to result in significant
merge conflicts with any open pull request, excluding about 20 files.
His plan is to merge the remaining changes with more precise care,
potentially involving merging parts of conflicting pull requests
before running the `eslint --fix` operation.

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2019-11-03 12:42:39 -08:00
Anders Kaseorg c3b4c0a229 frontend_tests: Use let with explicit null in components test.
Even though this variable was only assigned once, it was accessed
before its initialization, so it couldn’t be converted directly to
`let` or `const`.  Use `let` with an explicit `null` to make it
clearer what’s going on and satisfy ESLint.  (Why not `undefined`?
There’s an ESLint rule against that too.)

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2019-10-28 15:02:43 -07:00
Yashashvi Dave 80ceb1a46d components: Add `disable_tab` attribute. 2019-05-13 17:27:32 -07:00
Tim Abbott bdb3da4504 eslint: Add key-spacing linter rule.
Apparently, we didn't have one of these, and thus had a moderate
number of generally very old violations in the codebase.  Fix this and
clear the ones that exist..
2018-12-18 10:41:06 -08:00
Steve Howell 7b2f5ccabc Rename markdown-help to message-formatting.
This just makes the id match the name of the
menu item.
2018-08-31 11:51:22 -07:00
Shubham Dhama 51ae82fbcf left-sidebar: Fix opening of compose box on narrowing using hotkeys.
Explaining the problem a bit: When we narrow to a stream/private message
using `q+Enter`/`w+Enter` compose box opens which isn't desirable here.
The bug here was the propagation of event after getting handled in
`keydown_util.handle` to `hotkeys.process_enter_key`.

Fixes: #9679.
2018-06-09 12:53:24 -04:00
Steve Howell 8deb2fc9ef toggler: Always call back to callback function.
In our toggler component (the thing that handles tabs in things
like our markdown/search help, settings/org, etc.), we have
a callback mechanism when you switch to the tab.  We were
being tricky and only calling it when the tab changed.

It turns out it's better to just always call the callback,
since these things are often in modals that open and close,
and if you open a modal for the second time, you want to do
the callback task for whichever setting you're going to.

There was actually kind of a nasty bug with this, where the
keyboard handling in the keyboard-help modal worked fine the
first time you opened it, but then it didn't work the second
time (if you focused some other element in the interim), and
it was due to not re-setting the focus to the inner modal
because we weren't calling the callback.

Of course, there are pitfalls in calling the same callbacks
twice, but our callbacks should generally be idempotent
for other reasons.
2018-06-04 09:02:58 -07:00
Steve Howell 910fc842e2 node tests: Remove dead code in components.js. 2018-05-17 08:33:51 -07:00
Steve Howell 42435db492 Add run_test helper for individual tests.
This run_test helper sets up a convention that allows
us to give really short tracebacks for errors, and
eventually we can have more control over running
individual tests.  (The latter goal has some
complications, since we often intentionally leak
setup in tests.)
2018-05-15 08:24:44 -07:00
Steve Howell 5f53fb1561 refactor: Remove factory code for toggle component.
We now have components.toggle simply return an object, without
putting the object into a lookup table.  The consumers of the
objects have all been changed to just store the object in their
own module scope.

The diff is a bit hard to read here, but it's mostly de-denting
code and removing these things:

        - we don't have opts.name
        - we don't have __toggle.lookup
        - we don't have keys
        - we don't create a sibling object to the prototype object
2018-04-20 13:45:58 -07:00
Steve Howell 27770d7f6b Fix recent pitfall in toggle component.
This is a recent regression where we I refactored the toggle
component.  For some reason the old code was waiting until
after the callback to set some of its state, and I did the
same thing when I simplified how the state was stored.

Under the old code, this didn't manifest as a bug, although
the old code was problematic for other reasons.

This "fix" doesn't actually change anything user facing, as the
follow up commit fixes the proximal problem more directly. And
the toggle component is still prone to people writing code that
tries to inspect the state of the widget as it's being built.
2018-04-04 16:37:39 -07:00
Steve Howell bd591424e2 Add keydown_util.js module.
This is a pretty thin abstraction to prevent having to put
magic numbers in code, doing the which/keyCode hack, and remembering
to all preventDefault.

Hopefully we'll expand it to handle things like shift/alt keys
for components that want their own keyboard handlers (vs. going
through hotkey.js).
2018-04-04 16:37:39 -07:00
Steve Howell 90e10a11de components: Simplify toggle component.
This adds some helpers to avoid some duplication, and we also
now track the selected idx directly, since it's all under our
control.

The main addition is `select_tab`, which we now use for some
things that used to simulate clicks.
2018-03-29 16:13:46 -07:00
Steve Howell e145258fee node tests: Add 100% coverage for components.js. 2018-03-29 08:09:38 -07:00