Commit Graph

138 Commits

Author SHA1 Message Date
Anders Kaseorg 719546641f js: Convert a.indexOf(…) !== -1 to a.includes(…).
Babel polyfills this for us for Internet Explorer.

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 K from "ast-types/gen/kinds";
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);

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;

  recast.visit(ast, {
    visitBinaryExpression(path) {
      const { operator, left, right } = path.node;
      if (
        n.CallExpression.check(left) &&
        n.MemberExpression.check(left.callee) &&
        !left.callee.computed &&
        n.Identifier.check(left.callee.property) &&
        left.callee.property.name === "indexOf" &&
        left.arguments.length === 1 &&
        checkExpression(left.arguments[0]) &&
        ((["===", "!==", "==", "!=", ">", "<="].includes(operator) &&
          n.UnaryExpression.check(right) &&
          right.operator == "-" &&
          n.Literal.check(right.argument) &&
          right.argument.value === 1) ||
          ([">=", "<"].includes(operator) &&
            n.Literal.check(right) &&
            right.value === 0))
      ) {
        const test = b.callExpression(
          b.memberExpression(left.callee.object, b.identifier("includes")),
          [left.arguments[0]]
        );
        path.replace(
          ["!==", "!=", ">", ">="].includes(operator)
            ? test
            : b.unaryExpression("!", test)
        );
        changed = true;
      }
      this.traverse(path);
    },
  });

  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-10 14:08:12 -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 442ff64836 notifications: Convert notice_memory from object to Map.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 17:24:43 -08:00
Pragati Agrawal b975d693bd stream_edit: Fix realm time sync of notifications setting checkbox.
This fixes the buggy behavior for streams which inherits the notification
setting from UserProfile, and are actively opened in "Streams > Stream
settings", if a user has opened two browser windows, and changes the
notification setting from "Settings > Notifications", then the changes
don't reflect such "Streams > Stream settings" notification setting
checkboxes for such stream.

Partially fixes: #12304.
2020-02-04 13:53:27 -08:00
Tim Abbott 2eae0b3e57 notifications: Support wildcard_mentions_notify for desktop.
In 1fe4f795af, we added the
wildcard_mentions_notify setting, which controls whether wildcard
mentions should be treated as mentions for the purposes of
notifications.  The original implementation focused on the more
important area of email/push notifications, and neglected to address
desktop notifications for wildcard mentions.

This change makes the wildcard_mentions_notify flag behave correctly
for desktop/sound notifications, including unit tests.

Fixes #13073.
2019-12-10 13:12:36 -08:00
Tim Abbott 22cefeede8 notifications: Extract should_send_*_notification for testing. 2019-12-10 12:54:36 -08:00
Anders Kaseorg 16ea89ad89 js: Automatically convert var to let and const in remaining files.
This commit was automatically generated by `tools/lint --only=eslint
--fix`, except for the `.eslintrc.json` change itself.

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2019-11-20 23:04:01 -08:00
Anders Kaseorg d17b577d0c js: Purge useless IIFEs.
With webpack, variables declared in each file are already file-local
(Global variables need to be explicitly exported), so these IIFEs are
no longer needed.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2019-10-25 13:51:21 -07:00
Vinit Singh d09a80260b lint: Replace local variables named 'msgid' with 'message_id'.
Follow up of commit 2a1305d. Replace all local variables named 'msgid'
with 'message_id' in all JS and HTML files, and adds a linter rule for
it as well.

Resolves #12952.
2019-08-28 15:19:30 -07:00
Priyank Patel e69c2f1aa2 notifications: Send message received from desktop app notification reply.
Adds a electron_bridge event that takes in message id and reply recived from
the notification reply and sends a message. We do this in webapp so desktop
doesn't have to depend on narrow and channel modules.

We also modify zjunit to reset window.electron_bridge after every run
to avoid leaking it.
2019-07-22 17:20:44 -07:00
YashRE42 9f5fca5579 notifications: Refactor and test notifiable unreads logic.
In this refactor, we extract two functions in unread.js.  Which one to
use depends on whether res has already been fetched or not.

This also adds node tests to maintain coverage of unread.js.

Tweaked by tabbott for cleaner variable names and tests.
2019-07-21 14:56:42 -07:00
David Wood 9bace3f2cd notifications: Allow only notifiable in unread count.
This commit adds a new setting to the user's notification settings that
will change the behaviour of the unread count in the title bar and
desktop application.

When enabled, the title bar will show the count of unread private messages
and mentions. When disabled, the title bar will act as before, showing
the total number of unread messages.

Fixes #1736.
2019-07-13 15:49:04 -07:00
Anders Kaseorg db0b33842c templates: Replace templates.render with require calls.
This removes an unnecessary layer of indirection and allows webpack to
catch filename mistakes.

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2019-07-12 21:11:14 -07:00
Yashashvi Dave e0a78af494 static/js/stream_data: Extract function `receives_notifications`. 2019-06-24 14:46:45 -07:00
Yashashvi Dave ee072da47a static/js/settings_notifications: Deduplicate code. 2019-06-12 16:24:51 -07:00
Seth Nickell 93696729c6 notifications: Disable default permission pop up.
Prior to this commit, we'd put up the green "Enable desktop
notifications" bar on page load AND the first time a desktop
notification worthy message was received, it would attempt to notify,
automatically triggering a browser permission popup (the same one as
clicking the green bar results in).

Now, desktop notifications are not attempted at all until the green
bar is clicked. Additionally Firefox and Webkit browser-specific
checks are made more uniform and done at the same point.

Tested written by YashRE42.

Fixes #11504.
2019-06-12 16:12:13 -07:00
Yashashvi Dave 784d02bf60 static/js/stream_data: Rename `in_home_view` functions. 2019-05-30 21:39:06 -07:00
Mohit Gupta bf14f4cd7b notification: Show wrong narrow notification for non locally echoed message.
Show "sent to different narrow" notification and other such notification by
notifications.notify_local_mixes for non locally echoed message sent by
current client.

With significant new comments added by tabbott.

Fixes: #11488.
2019-02-13 15:51:41 -08:00
Mohit Gupta e5f28ca78e refactor: Rename locally_echoed to sent_by_this_client.
This is a bit clearer, since we will soon want to pass this option for
messages that could not be locally echoed due to markdown rendering.
2019-02-13 15:30:57 -08:00
Steve Howell b3594c984a message scrolling: Fix "Scroll down to view" warning.
We recently added a feature to warn users that they
may need to scroll down to view messages that they
just sent, but it was broken due to various complexities
in the rendering code path.

Now we compute it a bit more rigorously.

It requires us to pass some info about rendering up
and down the stack, which is why it's kind of a long
commit, but the bulk of the logic is in these JS files:

    * message_list_view.js
    * notifications.js

I choose to pass structs around instead of booleans,
because I anticipate we may eventually add more metadata
about rendering to it, plus bools are just kinda brittle.
(The exceptions are that `_maybe_autoscroll`, which
is at the bottom of the stack, just passes back a simple
boolean, and `notify_local_mixes`, also at the bottom
of the stack, just accepts a simple boolean.)

This errs on the side of warning the user, even if the
new message is partially visible.

Fixes #11138
2019-01-07 17:17:55 -08:00
Steve Howell ed0abb8a53 minor: Move code around for setting link id/text/class.
We don't need to compute these vars if we early exit.
2019-01-07 17:11:17 -08:00
Steve Howell 053a41d816 subject -> topic: Fix notifications.js. 2018-12-29 14:34:06 -08:00
Vaibhav 7371fd2647 notifications: Refactor code using logic from message_viewport.
Logic for checking if the last message in the current table is visible was
already written in message_viewport.js; Code in notifications.js is changed
to reduce redundancy.
2018-12-18 11:53:08 -08:00
Tim Abbott bdc4876948 notifications: Fix missing translation tags for above-compose alerts.
Apparently, these had never made it to being translated.  Since
they're an important part of the user experience, we add translation
tags for them now.
2018-12-16 11:14:09 -08:00
Tim Abbott 6c7725d21f notifications: Compute link earlier in mix notifications code.
This should make it more obvious how to later add a feature to include
a link for out-of-view-scroll-down notifications, should we ever want
that.
2018-12-16 11:02:52 -08:00
Vaibhav 372cb20f9e notifications: Notify when sent message is scrolled down in view.
A common source of confusion for new users is sending a message when
you're scrolled up in the message feed; in this case, it's nice to
communicate to the user why the message is not in view.

Fixes #10792.

Restructured by tabbott to replace overly complex logic for getting
the position of the new message with a `message_list.get_row()` call.
2018-12-16 10:59:25 -08:00
Steve Howell a8718c9051 muting: Use stream_id for internal data structures.
This fixes the most core data structures inside of
muting.js.  We still use stream names for incoming
data to set_muted_topics and outgoing data from
get_muted_topics.

This will make us more resilient to stream name changes.
Before, if you were logged on when a stream rename
occured, topics that were muted under that stream would
appear to be unmuted.  (You could fix it with a reload,
but it can be jarring to have a bunch of unread messages
appear in your feed suddenly.)

Fixes #11033
2018-12-14 15:58:35 -08:00
Vishnu Ks e5b3d39ce9 messages: Show banner when message history is limited.
This communicates to users clearly about the situation when the
history_limited flag is set by the backend (because message history
was cutoff).
2018-12-13 09:02:11 -08:00
Marco Burstein ba46dc83c6 notifications: Add a setting for changing the notification sound.
Also, add a new notification sound, "ding". It comes from
https://freesound.org, where the original Zulip notification sound comes
from as well. In the future, new sounds can be added by adding audio
files to the `static/audio/notification_sounds` directory.

Tweaked significantly by tabbott:
* Avoided removing static/audio/zulip.ogg, because that file is
  checked for by old versions of the desktop app.
* Added a views check for the sound being valid + tests.
* Added additional tests.
* Restructured the test_events test to be cleaner.
* Removed check_bool_or_string.
* Increased max length of notification_sound.
* Provide available_notification_sounds in events data set if global
  notifications settings are requested.

Fixes #8051.
2018-12-09 21:25:30 -08:00
Steve Howell 91e4784b92 subject -> topic: Rename narrow.by_subject. 2018-11-14 23:24:06 -08:00
Steve Howell 6c1a96174e subject -> topic: Rename narrow_by_subject. 2018-11-14 23:24:06 -08:00
Akash Nimare 2385b3d1d3 notification: Add a space in narrow to message content.
We have a space for this kind of texts in other places but somehow we
missed this case. This PR fixes the same.
2018-09-17 13:58:29 -04:00
Armaan Ahluwalia 6d255efe4c app: Prepare JS files for consumption by webpack.
This commit prepares the frontend code to be consumed by webpack.

It is a hack: In theory, modules should be declaring and importing the
modules they depend on and the globals they expose directly.

However, that requires significant per-module work, which we don't
really want to block moving our toolchain to webpack on.

So we expose the modules by setting window.varName = varName; as
needed in the js files.
2018-07-05 10:53:36 +02:00
Shubham Dhama 80a2d5bc59 eslint: Enable `conditionalAssign` config of no-trailing-spaces rule. 2018-06-11 07:51:24 -04:00
Shubham Dhama dcb6254a4e eslint: Enable `no-extra-parens` rule.
Following sub-configuration is disabled:
                "nestedBinaryExpressions": false,
2018-06-11 07:51:24 -04:00
Shubham Dhama cc03f9fb8f eslint: Enable space-infix-ops rule.
More about rule at  https://eslint.org/docs/rules/space-infix-ops
2018-06-05 00:47:35 +05:30
Tim Abbott 1188f4a3e3 notifications: Remove remaining basic window.bridge logic. 2018-05-15 16:00:30 -07:00
Tim Abbott 954fd8178f desktop: Remove logic for legacy QT/webkit desktop app.
We leave around a few comments that may help the new electron desktop
app do similar things in the future.
2018-05-15 16:00:14 -07:00
Tim Abbott 7ab8a8e820 js: Fix a bunch of indentation issues found by eslint.
This is preparation for enabling an eslint indentation configuration.
90% of these changes are just fixes for indentation errors that have
snuck into the codebase over the years; the others are more
significant reformatting to make eslint happy (that are not otherwise
actually improvements).

The one area that we do not attempt to work on here is the
"switch/case" indentation.
2018-05-06 16:25:02 -07:00
Tim Abbott e4c50ff4fd narrow: Remove unnecessary select_first_unread option.
We consistently either pass a `then_select_id` into narrow.activate,
or were using the select_first_unread option.  Now, we just compute
select_first_unread based on the value of then_select_id.
2018-04-22 21:33:33 -07:00
Rohitt Vashishtha 7a4788b364 node-tests: Add basic tests for notifications API.
This commit exposes some inner variables of notifications.js to make
them easily testable. The first test added simply checks whether the
showing and closing of notifications works properly, and doesn't yet
verify the main code logic of the notification generation.
2018-04-13 09:13:50 -07:00
Priyank cd48236756 electron_bridge: Send unread count to electron app on update. 2018-03-09 14:12:33 -08:00
Shubham Dhama a0ab87bef2 notifications: Clean and automate global notifications update handler.
To prevent specifying notifications individually for global
updates, automate handle_global_notification_updates using
settings_notifications.notification_settings where we have
the keys of all the types of notifications.
2018-03-08 07:19:48 -08:00
Catherine Kleimeier d032e1ad96 Node Unit Tests: Create test for notifications.message_is_notifiable
We create a node unit test,
with 'muting' and 'stream_data' modules as dependencies,
to test the logic in notifications.message_is_notifiable.

Part of #2945
2018-02-26 16:50:14 -05:00
Roman Godov b875fe07eb settings: Added setting to turn on and off realm name in email subject.
Users having only account in one realm will not be distracted by realm
name in subject lines of every email.  Users who have multiple
accounts in realms can turn this setting on and receive a
corresponding realm name in email's subject.

Tweaked by tabbott to rebase and address a few small issues.

Fixes #5489.
2018-02-05 18:01:54 -08:00
Greg Price 9798bb51c8 notifications: Restore a comment explaining `received_messages`.
A comment like this was removed in
  fa44d2ea6 "settings: Remove autoscroll_forever setting."
The comment went on to say something about autoscroll, but this
part still seems relevant.  While here, adjust grammar and caps.
2018-01-31 07:51:16 -05:00
YJDave fa44d2ea69 settings: Remove autoscroll_forever setting.
Fixes #6845
2018-01-02 10:35:49 -05:00
Brock Whittaker 4b45878946 notifications: If "Notification" is undefined, just return "denied".
We do not want the code to lead to a path where it will attempt to
display native notifications if the “Notification” object doesn’t
exist, as this likely means that the device does not support OS
notifications.
2017-10-23 21:29:42 -07:00
Brock Whittaker 5889132732 notifications: Remove test for "webkit" in userAgent.
This removes a test for "webkit" in the userAgent string in order
to see whether notifications should be displayed. This is so that
the notifications process will work correctly in Firefox and not
keep registering as "false" which makes the notifications prompt
continue to re-show itself.
2017-10-19 15:01:12 -07:00
Brock Whittaker 7107d19aeb notifications: Detect whether notifications are blocked.
This checks whether the user is already in the state of having
blocked notifications, so that we can *not* show them the banner
to enable notifications, since browsers won't allow the request
to go through again.

Perhaps in a follow up we should create a different banner for
this case that shows how to enable notifications at the browser
level for this site.
2017-10-18 21:55:43 -07:00