├── .circleci └── config.yml ├── .gitignore ├── .prepare-release.sh ├── ISSUE_TEMPLATE.md ├── LICENSE ├── app ├── assets │ ├── badges │ │ ├── badge-0.png │ │ ├── badge-1.png │ │ ├── badge-2.png │ │ ├── badge-3.png │ │ ├── badge-4.png │ │ ├── badge-5.png │ │ ├── badge-6.png │ │ ├── badge-7.png │ │ ├── badge-8.png │ │ └── badge-9.png │ ├── icon │ │ ├── icon.png │ │ ├── icon@1.25x.png │ │ ├── icon@1.5x.png │ │ ├── icon@2x.png │ │ ├── iconWarning.png │ │ ├── iconWarningWithMsg.png │ │ └── iconWithMsg.png │ └── img │ │ ├── trayTemplate.png │ │ └── trayTemplate@2x.png ├── css │ └── settings.css ├── html │ ├── about.html │ ├── phoneinfo.html │ └── settings.html ├── js │ ├── injected.js │ └── views │ │ ├── about.js │ │ ├── phoneinfo.js │ │ └── settings.js ├── locale │ ├── de_DE │ │ └── messages.po │ ├── en_US │ │ └── messages.po │ ├── es_ES │ │ └── messages.po │ ├── it_IT │ │ └── messages.po │ ├── messages.pot │ ├── pt_BR │ │ └── messages.po │ ├── ru_RU │ │ └── messages.po │ └── tr_TR │ │ └── messages.po ├── main.js ├── menu.js └── package.json ├── assets └── icons │ └── whatsupp.png ├── debian ├── changelog ├── compat ├── control ├── copyright ├── docs ├── postinst ├── prerm ├── rules └── source │ └── format ├── eu.alindt.whatsupp.appdata.xml ├── package.json ├── packager.json ├── readme.md ├── whatsupp.desktop └── whatsupp.spec /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # vim: set ts=2 sw=2 expandtab: 2 | 3 | version: 2 4 | jobs: 5 | build: 6 | docker: 7 | - image: circleci/node:dubnium 8 | 9 | working_directory: ~/repo 10 | 11 | steps: 12 | - checkout 13 | 14 | - run: 15 | name: Install dependencies 16 | command: | 17 | curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - 18 | echo "deb http://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list 19 | sudo apt-get update 20 | sudo apt-get install --no-install-recommends yarn fakeroot 21 | 22 | # Download and cache dependencies 23 | - restore_cache: 24 | name: Restore Yarn Package Cache 25 | keys: 26 | - yarn-packages-v1-{{ checksum "package.json" }}-{{ checksum "app/package.json" }} 27 | # fallback to using the latest cache if no exact match is found 28 | - yarn-packages-v1 29 | 30 | - run: 31 | name: Yarn Install 32 | command: | 33 | /usr/bin/yarn install 34 | 35 | - save_cache: 36 | paths: 37 | - node_modules 38 | - app/node_modules 39 | key: yarn-packages-{{ checksum "package.json" }}-{{ checksum "app/package.json" }} 40 | 41 | - run: /usr/bin/yarn build:linux64 42 | - run: /usr/bin/yarn build:linux32 43 | - run: /usr/bin/yarn pkg:debian64 44 | - run: /usr/bin/yarn pkg:debian32 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | .DS_Store 3 | Thumbs.db 4 | dist 5 | npm-debug.log 6 | node_modules 7 | electron-* 8 | *.mo 9 | .pc 10 | *.log 11 | *.substvars 12 | *.EX 13 | debian/whatsupp/ 14 | debian/files 15 | dummy.tar.bz2 16 | rpmbuild/ 17 | debian/debhelper-build-stamp 18 | *.swp 19 | **/yarn.lock 20 | -------------------------------------------------------------------------------- /.prepare-release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | node -v 2>&1 > /dev/null 4 | if [ $? -ne 0 ]; then 5 | echo "Missing nodejs executable" 6 | exit 1 7 | fi 8 | 9 | editor package.json 10 | editor app/package.json 11 | editor debian/changelog 12 | editor whatsupp.spec 13 | editor eu.alindt.whatsupp.appdata.xml 14 | 15 | yarn 16 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### System details 2 | 3 | * OS: [your distribution's name, version, language] 4 | * App Version: [the app version, or "github" if you're using latest from github (e.g.: 0.5.1)] 5 | * Desktop Environment: [desktop environment (e.g.: GNOME 3.22)] 6 | 7 | ### Expected behaviour 8 | 9 | [what you were expecting from an action (specified below)] 10 | 11 | ### Actual behaviour 12 | 13 | [what really happened] 14 | 15 | ### Step to reproduce the behaviour 16 | 17 | [steps to do in order to reproduce the bad behavior] 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | {one line to give the program's name and a brief idea of what it does.} 635 | Copyright (C) {year} {name of author} 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | {project} Copyright (C) {year} {fullname} 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /app/assets/badges/badge-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/badges/badge-0.png -------------------------------------------------------------------------------- /app/assets/badges/badge-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/badges/badge-1.png -------------------------------------------------------------------------------- /app/assets/badges/badge-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/badges/badge-2.png -------------------------------------------------------------------------------- /app/assets/badges/badge-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/badges/badge-3.png -------------------------------------------------------------------------------- /app/assets/badges/badge-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/badges/badge-4.png -------------------------------------------------------------------------------- /app/assets/badges/badge-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/badges/badge-5.png -------------------------------------------------------------------------------- /app/assets/badges/badge-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/badges/badge-6.png -------------------------------------------------------------------------------- /app/assets/badges/badge-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/badges/badge-7.png -------------------------------------------------------------------------------- /app/assets/badges/badge-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/badges/badge-8.png -------------------------------------------------------------------------------- /app/assets/badges/badge-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/badges/badge-9.png -------------------------------------------------------------------------------- /app/assets/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/icon/icon.png -------------------------------------------------------------------------------- /app/assets/icon/icon@1.25x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/icon/icon@1.25x.png -------------------------------------------------------------------------------- /app/assets/icon/icon@1.5x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/icon/icon@1.5x.png -------------------------------------------------------------------------------- /app/assets/icon/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/icon/icon@2x.png -------------------------------------------------------------------------------- /app/assets/icon/iconWarning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/icon/iconWarning.png -------------------------------------------------------------------------------- /app/assets/icon/iconWarningWithMsg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/icon/iconWarningWithMsg.png -------------------------------------------------------------------------------- /app/assets/icon/iconWithMsg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/icon/iconWithMsg.png -------------------------------------------------------------------------------- /app/assets/img/trayTemplate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/img/trayTemplate.png -------------------------------------------------------------------------------- /app/assets/img/trayTemplate@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/app/assets/img/trayTemplate@2x.png -------------------------------------------------------------------------------- /app/css/settings.css: -------------------------------------------------------------------------------- 1 | html{ 2 | -webkit-user-select: none; 3 | user-select: none; 4 | } 5 | 6 | header { 7 | -webkit-app-region: drag; 8 | display: block; 9 | border-bottom: 1px solid #ccc 10 | } 11 | 12 | header h4 { 13 | margin-top: 2px; 14 | } 15 | 16 | main { 17 | margin: 10px auto; 18 | padding: 20px; 19 | } 20 | 21 | #save-button{ 22 | bottom: 0; 23 | right: 0; 24 | } 25 | 26 | label:after { 27 | width: 200px 28 | } 29 | -------------------------------------------------------------------------------- /app/html/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | 14 | 15 | 25 | About 26 | 27 | 28 |
29 |
30 |

31 |
32 | 33 |
34 |

Native desktop app/wrapper for https://web.whatsapp.com. Built with Electron.

35 |

App version:

36 |

37 |

Website: https://github.com/alindt/WhatsUpp

38 |
39 | 40 |
41 |
Disclaimer
42 |

This is NOT an official product. This project does not attempt to reverse engineer the WhatsApp API or attempt to 43 | reimplement any part of the WhatsApp client. Any communication between the user and WhatsApp servers is handled by 44 | official WhatsApp Web itself; this is just a native wrapper for WhatsApp Web, like a browser.

45 |
46 |
47 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /app/html/phoneinfo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | Phone Info 15 | 16 | 17 |
18 |
19 |

Phone Info

20 |
21 | 22 |
23 |
24 |
25 |

Mobile number:

26 |

Battery:

27 |

Phone: 28 |

29 |

WhatsApp version:

30 |
31 |
32 | 33 |
34 |
35 | Close 36 |
37 |
38 |
39 |
40 | 41 | 42 | -------------------------------------------------------------------------------- /app/html/settings.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | 14 | 15 | 36 | 37 | 38 | 39 |
40 |
41 |

42 |
43 |
44 |

45 | 49 |

50 |

51 | 55 |

56 |

57 | 61 |

62 |

63 | 67 |

68 |

69 | 73 |

74 |

75 | 79 |

80 |

81 | 85 |

86 |

87 | 91 |

92 |

93 | 97 |

98 |

99 | 103 |

104 |

105 | 109 |

110 | 111 |
112 | 116 |
117 | 118 |
119 |
120 | 121 |

122 |

123 | 124 |
125 | 131 |
132 |
133 |

134 | 135 |

136 | 140 |

141 | 142 |
143 |
144 | 152 |
153 |
154 | 155 |
156 |
157 | 158 |

159 | 163 |

164 | 165 |
166 |
167 |
168 | folder 169 | 170 |
171 |
172 | 173 |
174 |
175 | 176 |
177 | 178 |
179 | 180 |
181 |
182 |
183 | 184 |

185 | 190 |

191 | 192 |
193 |
194 | 200 | 204 | 205 | 206 | -------------------------------------------------------------------------------- /app/js/injected.js: -------------------------------------------------------------------------------- 1 | // vim: set ts=2 sw=2 expandtab: 2 | /* global MutationObserver, Notification */ 3 | 4 | (function () { 5 | const { ipcRenderer } = require('electron') 6 | const { remote } = require('electron') 7 | let updatePhoneInfoInterval = null 8 | 9 | function updatePhoneInfo () { 10 | if (window.Store === undefined || window.Store.Conn === undefined) { 11 | return 12 | } 13 | ipcRenderer.send('phoneinfoupdate', { 14 | info: window.Store.Stream.info, 15 | me: '+' + window.Store.Conn.me.split('@')[0], 16 | battery: window.Store.Conn.battery, 17 | plugged: window.Store.Conn.plugged, 18 | platform: window.Store.Conn.platform, 19 | phoneActive: window.Store.Stream.phoneActive, 20 | phone: { 21 | manufacturer: window.Store.Conn.phone.device_manufacturer, 22 | model: window.Store.Conn.phone.device_model, 23 | mcc: window.Store.Conn.phone.mcc, 24 | mnc: window.Store.Conn.phone.mnc, 25 | os_build_number: window.Store.Conn.phone.os_build_number, 26 | os_version: window.Store.Conn.phone.os_version, 27 | wa_version: window.Store.Conn.phone.wa_version 28 | } 29 | }) 30 | if (updatePhoneInfoInterval != null) { 31 | clearInterval(updatePhoneInfoInterval) 32 | updatePhoneInfoInterval = null 33 | setInterval(updatePhoneInfo, 2000) 34 | } 35 | } 36 | 37 | console.log('Waiting for DOMContentLoaded') 38 | document.addEventListener('DOMContentLoaded', function () { 39 | console.log('DOMContentLoaded event') 40 | updatePhoneInfoInterval = setInterval(updatePhoneInfo, 500) 41 | 42 | // pass in the target node, as well as the observer options 43 | var observer = new MutationObserver(function (mutations) { 44 | console.log('Mutations occurred: ', mutations.length) 45 | // document.querySelector('div[data-asset-chat-background]').classList.add('pane-chat-tile') 46 | 47 | if (remote.getGlobal('config').currentSettings.darkMode) { 48 | const elements = document.getElementsByTagName('path') 49 | for (let i = 0; i < elements.length; i++) { 50 | elements[i].setAttribute('fill', 'white') 51 | } 52 | } 53 | 54 | const inputSearch = document.querySelector('input[type="text"][title="Search or start new chat"]') 55 | if (inputSearch) { 56 | console.log('Adding event listeners') 57 | 58 | document.addEventListener('keydown', function (event) { 59 | // ctrl+f focuses on search input. 60 | if (event.ctrlKey && event.key === 'f') { inputSearch.focus() } 61 | }) 62 | 63 | console.log('Disconnecting the observer') 64 | observer.disconnect() 65 | } 66 | }) 67 | 68 | const config = { childList: true, subtree: true } 69 | observer.observe(document.querySelector('body'), config) 70 | }, false) 71 | 72 | setInterval(function () { 73 | Array.from(document.querySelectorAll('audio')).map(function (audio) { 74 | audio.playbackRate = (window.audioRate || 1) 75 | }) 76 | if (window.audioRate) { 77 | Array.from(document.querySelectorAll('.meta-audio *:first-child')).map(function (span) { 78 | span.innerHTML = window.audioRate.toFixed(1) + 'x ' 79 | }) 80 | } 81 | }, 200) 82 | 83 | let NativeNotification = Notification 84 | // Notification = function (title, options) { 85 | NativeNotification = function (title, options) { 86 | if (remote.getGlobal('config').currentSettings.quietMode) { 87 | return 88 | } 89 | const notification = new NativeNotification(title, options) 90 | 91 | notification.addEventListener('click', function () { 92 | ipcRenderer.send('notificationClick') 93 | }) 94 | 95 | return notification 96 | } 97 | 98 | Notification.prototype = NativeNotification.prototype 99 | Notification.permission = NativeNotification.permission 100 | Notification.requestPermission = NativeNotification.requestPermission.bind(Notification) 101 | })() 102 | -------------------------------------------------------------------------------- /app/js/views/about.js: -------------------------------------------------------------------------------- 1 | /* global $ */ 2 | 3 | const whatsUpp = require('electron').remote.getGlobal('whatsUpp') 4 | const pjson = require('electron').remote.getGlobal('pjson') 5 | 6 | $(document).ready(() => { 7 | $('#appversion').html(pjson.version) 8 | $('#appname').html(pjson.productName) 9 | if (whatsUpp.newVersion === null) { 10 | $('#appupdates').css('color', 'red') 11 | $('#appupdates').html('Error while checking for updates.') 12 | } else if (whatsUpp.newVersion.localeCompare(pjson.version) === 1) { 13 | $('#appupdates').html('A new version is available: ' + whatsUpp.newVersion + '!') 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /app/js/views/phoneinfo.js: -------------------------------------------------------------------------------- 1 | // vim: set ts=2 sw=2 expandtab: 2 | 3 | /* global $ */ 4 | 5 | // var whatsUpp = require('electron').remote.getGlobal('whatsUpp') 6 | const phoneinfo = require('electron').remote.getGlobal('phoneinfo') 7 | 8 | const PhoneInfoView = { 9 | bindEvents () { 10 | // $this = this 11 | $('#close-button').on('click', () => { 12 | phoneinfo.window.close() 13 | }) 14 | }, 15 | 16 | init () { 17 | console.log(phoneinfo) 18 | if (phoneinfo.infos != null) { 19 | $('#me').html(phoneinfo.infos.me) 20 | $('#battery').html(phoneinfo.infos.battery + '% (' + (phoneinfo.infos.plugged ? 'charging' : 'discharging') + ')') 21 | $('#platform').html(phoneinfo.infos.platform) 22 | $('#manufacturer').html(phoneinfo.infos.phone.manufacturer) 23 | $('#model').html(phoneinfo.infos.phone.model) 24 | $('#os_version').html(phoneinfo.infos.phone.os_version) 25 | $('#wa_version').html(phoneinfo.infos.phone.wa_version) 26 | $('#os_build_number').html(phoneinfo.infos.phone.os_build_number) 27 | } else { 28 | $('#me').html('Not available, try to refresh this page') 29 | } 30 | this.bindEvents() 31 | } 32 | } 33 | 34 | $(document).ready(() => { 35 | PhoneInfoView.init() 36 | }) 37 | -------------------------------------------------------------------------------- /app/js/views/settings.js: -------------------------------------------------------------------------------- 1 | // vim: set ts=2 sw=2 expandtab: 2 | 3 | /* global $, _ */ 4 | 5 | const whatsUpp = require('electron').remote.getGlobal('whatsUpp') 6 | const settings = require('electron').remote.getGlobal('settings') 7 | const config = require('electron').remote.getGlobal('config') 8 | // const log = require('electron-log') 9 | // no-unused-vars:: const { dialog } = require('electron').remote 10 | 11 | const SettingsView = { 12 | bindEvents () { 13 | // $this = this 14 | $('#save-button').on('click', (e) => { 15 | e.preventDefault() 16 | if ($('.invalid').length > 0) { 17 | return 18 | } 19 | // $this.saveSettings() 20 | this.saveSettings() 21 | settings.window.close() 22 | }) 23 | 24 | $('#close-button').on('click', () => { 25 | settings.window.close() 26 | }) 27 | 28 | $('#customThumbSizeCheck').on('change', () => { 29 | $('#thumb-size').toggle() 30 | }) 31 | 32 | $('#useProxy').on('change', () => { 33 | $('#proxies').toggle() 34 | $('#proxyType').prop('disabled', !($('#useProxy').is(':checked'))) 35 | $('#proxyURI').prop('disabled', !($('#useProxy').is(':checked'))) 36 | }) 37 | 38 | $('#custombackground_enable').on('change', () => { 39 | $('#custombackground').toggle() 40 | }) 41 | }, 42 | 43 | init () { 44 | document.title = _('Settings') 45 | 46 | $('#custombackground_enable').attr('checked', config.get('background-image') !== undefined) 47 | if (config.get('background-image') !== undefined) { 48 | $('#custombackground_file').val(config.get('background-image')) 49 | $('#background_opacity').val(config.get('background-opacity')) 50 | } else { 51 | $('#background_opacity').val('100') 52 | $('#custombackground').hide() 53 | } 54 | 55 | if (config.get('fontSize') !== undefined) { 56 | $('#fontSize').val(config.get('fontSize')) 57 | } 58 | 59 | $('#darkMode').attr('checked', config.get('darkMode') === true) 60 | $('#blurImages').attr('checked', config.get('blurImages') === true) 61 | $('#escCloseMainWindow').attr('checked', config.get('escCloseMainWindow') === true) 62 | $('#autoHideMenuBar').attr('checked', config.get('autoHideMenuBar') === true) 63 | $('#disablegpu').attr('checked', config.get('disablegpu') === true) 64 | $('#globalshortcut').attr('checked', config.get('globalshortcut') === true) 65 | $('#autostart').attr('checked', config.get('autostart') === true) 66 | $('#startminimized').attr('checked', config.get('startminimized') === true) 67 | $('#trayicon').attr('checked', config.get('trayicon') !== false) 68 | $('#avatars').attr('checked', config.get('hideAvatars')) 69 | $('#previews').attr('checked', config.get('hidePreviews')) 70 | 71 | if (config.get('thumbSize') !== undefined) { 72 | $('#customThumbSizeCheck').prop('checked', true) 73 | $('#thumb-size').show() 74 | $('#thumb-size').val(config.get('thumbSize')) 75 | } else { 76 | $('#customThumbSizeCheck').prop('checked', false) 77 | $('#thumb-size').hide() 78 | } 79 | 80 | $('#useProxy').attr('checked', config.get('useProxy')) 81 | if ($('#useProxy').is(':checked')) { $('#proxies').show() } else { $('#proxies').hide() } 82 | $('#proxyType').val(config.get('proxyType')) 83 | $('#proxyURI').val(config.get('proxyURI')) 84 | 85 | $('#customcss_enable').attr('checked', config.get('customcss') !== undefined) 86 | if ($('#customcss_enable').is(':checked')) { 87 | $('#customcss_file').val(config.get('customcss')) 88 | } 89 | 90 | // Disable unavailable options 91 | if (process.platform === 'darwin') { 92 | $('#autostart').prop('disabled', true) 93 | $('#autoHideMenuBar').prop('disabled', true) 94 | $('#trayicon').prop('disabled', true) 95 | $('#trayicon').prop('checked', false) 96 | } 97 | 98 | this.bindEvents() 99 | }, 100 | 101 | saveSettings () { 102 | if ($('#customcss_enable').is(':checked')) { 103 | config.set('customcss', $('#customcss_file').val()) 104 | } else { 105 | config.set('customcss', undefined) 106 | } 107 | 108 | if ($('#custombackground_enable').is(':checked')) { 109 | config.set('background-image', $('#custombackground_file').val()) 110 | config.set('background-opacity', $('#background_opacity').val()) 111 | } else { 112 | config.set('background-image', undefined) 113 | } 114 | 115 | config.set('fontSize', $('#fontSize').val()) 116 | config.set('darkMode', $('#darkMode').is(':checked')) 117 | config.set('blurImages', $('#blurImages').is(':checked')) 118 | config.set('escCloseMainWindow', $('#escCloseMainWindow').is(':checked')) 119 | config.set('autoHideMenuBar', $('#autoHideMenuBar').is(':checked')) 120 | config.set('disablegpu', $('#disablegpu').is(':checked')) 121 | config.set('globalshortcut', $('#globalshortcut').is(':checked')) 122 | config.set('autostart', $('#autostart').is(':checked')) 123 | config.set('startminimized', $('#startminimized').is(':checked')) 124 | config.set('hideAvatars', $('#avatars').is(':checked')) 125 | config.set('hidePreviews', $('#previews').is(':checked')) 126 | config.set('thumbSize', parseInt($('#thumb-size').val(), 10)) 127 | config.set('trayicon', $('#trayicon').is(':checked')) 128 | 129 | if ($('#customThumbSizeCheck').is(':checked')) { 130 | config.set('thumbSize', $('#thumb-size').val()) 131 | } else { 132 | config.unSet('thumbSize') 133 | } 134 | 135 | if ($('#proxyType').val() != null && $('#proxyURI').val() !== '') { 136 | config.set('useProxy', $('#useProxy').is(':checked')) 137 | config.set('proxyType', $('#proxyType').val()) 138 | config.set('proxyURI', $('#proxyURI').val()) 139 | } else { 140 | config.set('useProxy', false) 141 | config.unSet('proxyType') 142 | config.unSet('proxyURI') 143 | } 144 | 145 | config.saveConfiguration() 146 | config.applyConfiguration() 147 | 148 | // Remove ServiceWorker to allow reloading 149 | // whatsUpp.clearCache(); 150 | whatsUpp.window.webContents.unregisterServiceWorker(function () { return true }) 151 | 152 | whatsUpp.window.reload() 153 | } 154 | } 155 | 156 | /* no-unused-vars 157 | function chooseCustomCSS () { 158 | if ($('#customcss_enable').is(':checked')) { 159 | dialog.showOpenDialog(function (fileNames) { 160 | if (fileNames === undefined || fileNames.length === 0) { 161 | $('#customcss_enable').removeAttr('checked') 162 | return 163 | } 164 | $('#customcss_file').val(fileNames[0]) 165 | }) 166 | } else { 167 | $('#customcss_file').val('') 168 | } 169 | } 170 | */ 171 | 172 | /* no-unused-vars 173 | function chooseChatBackground () { 174 | if ($('#custombackground_enable').is(':checked')) { 175 | dialog.showOpenDialog(function (fileNames) { 176 | if (fileNames === undefined || fileNames.length === 0) { 177 | $('#custombackground_enable').removeAttr('checked') 178 | return 179 | } 180 | if (fileNames[0].endsWith('.jpg') || fileNames[0].endsWith('.jpeg') || 181 | fileNames[0].endsWith('.png') || 182 | fileNames[0].endsWith('.gif')) { 183 | $('#custombackground_file').val(fileNames[0]) 184 | } else { 185 | alert(_('Please choose a JPEG or PNG file')) 186 | $('#custombackground_enable').removeAttr('checked') 187 | } 188 | }) 189 | } else { 190 | $('#custombackground_file').val('') 191 | } 192 | } 193 | */ 194 | 195 | $(document).ready(() => { 196 | SettingsView.init() 197 | }) 198 | -------------------------------------------------------------------------------- /app/locale/de_DE/messages.po: -------------------------------------------------------------------------------- 1 | # WhatsUpp translations. 2 | # 3 | msgid "" 4 | msgstr "" 5 | "Project-Id-Version: WhatsUpp\n" 6 | "Report-Msgid-Bugs-To: \n" 7 | "POT-Creation-Date: 2017-06-17 11:15+0200\n" 8 | "PO-Revision-Date: 2017-11-28 10:48+0100\n" 9 | "Language-Team: \n" 10 | "MIME-Version: 1.0\n" 11 | "Content-Type: text/plain; charset=UTF-8\n" 12 | "Content-Transfer-Encoding: 8bit\n" 13 | "X-Generator: Poedit 2.0.4\n" 14 | "Last-Translator: mrprobot\n" 15 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 16 | "Language: de_DE\n" 17 | 18 | #: app/main.js:168 app/main.js:192 app/main.js:198 app/main.js:214 19 | msgid "Show" 20 | msgstr "Anzeigen" 21 | 22 | #: app/main.js:174 app/menu.js:146 app/main.js:198 app/menu.js:159 23 | #: app/main.js:204 app/main.js:220 24 | msgid "Hide" 25 | msgstr "Ausblenden" 26 | 27 | #: app/main.js:181 app/menu.js:163 app/menu.js:191 app/main.js:205 28 | #: app/menu.js:176 app/menu.js:204 app/main.js:211 app/menu.js:197 29 | #: app/main.js:227 30 | msgid "Quit" 31 | msgstr "Beenden" 32 | 33 | #: app/menu.js:6 34 | msgid "Edit" 35 | msgstr "Bearbeiten" 36 | 37 | #: app/menu.js:9 38 | msgid "Undo" 39 | msgstr "Rückgängig" 40 | 41 | #: app/menu.js:14 42 | msgid "Redo" 43 | msgstr "Wiederherstellen" 44 | 45 | #: app/menu.js:22 46 | msgid "Cut" 47 | msgstr "Ausschneiden" 48 | 49 | #: app/menu.js:27 50 | msgid "Copy" 51 | msgstr "Kopieren" 52 | 53 | #: app/menu.js:32 54 | msgid "Paste" 55 | msgstr "Einfügen" 56 | 57 | #: app/menu.js:37 58 | msgid "Select All" 59 | msgstr "Alles auswählen" 60 | 61 | #: app/menu.js:45 app/html/settings.html:20 62 | msgid "Settings" 63 | msgstr "Einstellungen" 64 | 65 | #: app/menu.js:54 66 | msgid "View" 67 | msgstr "Ansicht" 68 | 69 | #: app/menu.js:57 70 | msgid "Reload" 71 | msgstr "Neu laden" 72 | 73 | #: app/menu.js:65 74 | msgid "Toggle Full Screen" 75 | msgstr "Vollbild" 76 | 77 | #: app/menu.js:78 78 | msgid "Toggle Developer Tools" 79 | msgstr "Entwickler Werkzeuge" 80 | 81 | #: app/menu.js:93 app/menu.js:106 82 | msgid "Window" 83 | msgstr "Fenster" 84 | 85 | #: app/menu.js:97 app/menu.js:110 86 | msgid "Minimize" 87 | msgstr "Minimieren" 88 | 89 | #: app/menu.js:102 app/html/settings.html:56 app/menu.js:115 90 | #: app/html/settings.html:60 app/html/settings.html:64 91 | #: app/html/settings.html:68 92 | msgid "Close" 93 | msgstr "Schließen" 94 | 95 | #: app/menu.js:109 app/menu.js:122 96 | msgid "Audio" 97 | msgstr "Lautstärke" 98 | 99 | #: app/menu.js:112 app/menu.js:125 100 | msgid "Increase Audio Rate by 20%" 101 | msgstr "Lautstärke um 20% erhöhen" 102 | 103 | #: app/menu.js:121 app/menu.js:134 104 | msgid "Decrease Audio Rate by 20%" 105 | msgstr "Lautstärke um 20% senken" 106 | 107 | #: app/menu.js:139 app/menu.js:184 app/menu.js:152 app/menu.js:197 108 | msgid "About" 109 | msgstr "Über" 110 | 111 | #: app/menu.js:151 app/menu.js:164 112 | msgid "Hide Others" 113 | msgstr "Andere ausblenden" 114 | 115 | #: app/menu.js:156 app/menu.js:169 116 | msgid "Show All" 117 | msgstr "Alles anzeigen" 118 | 119 | #: app/menu.js:175 app/menu.js:188 120 | msgid "Bring All to Front" 121 | msgstr "Alle in Vordergrund bringen" 122 | 123 | #: app/html/settings.html:25 124 | msgid "Hide Avatars" 125 | msgstr "Avatare ausblenden" 126 | 127 | #: app/html/settings.html:29 128 | msgid "Hide Message Previews" 129 | msgstr "Nachrichten Vorschau ausblenden" 130 | 131 | #: app/html/settings.html:40 app/html/settings.html:44 132 | #: app/html/settings.html:48 app/html/settings.html:52 133 | msgid "Use Proxy (Changes in proxy settings require app restart)" 134 | msgstr "Proxy verwenden (Änderungen benötigen Neustart der App)" 135 | 136 | #: app/html/settings.html:50 app/html/settings.html:54 137 | #: app/html/settings.html:58 app/html/settings.html:62 138 | msgid "Https Proxy" 139 | msgstr "Https Proxy" 140 | 141 | #: app/html/settings.html:57 app/html/settings.html:61 142 | #: app/html/settings.html:65 app/html/settings.html:69 143 | msgid "Save" 144 | msgstr "Speichern" 145 | 146 | #: app/menu.js:91 147 | msgid "Phone info" 148 | msgstr "Telefon Info" 149 | 150 | #: app/html/settings.html:33 151 | msgid "Show Tray Icon" 152 | msgstr "Symbol im Tray anzeigen" 153 | 154 | #: app/html/settings.html:37 155 | msgid "Minimize to tray on startup" 156 | msgstr "Minimiert starten" 157 | 158 | #: app/html/settings.html:41 159 | msgid "Auto start on login" 160 | msgstr "Autostart" 161 | -------------------------------------------------------------------------------- /app/locale/en_US/messages.po: -------------------------------------------------------------------------------- 1 | # WhatsUpp translations. 2 | # 3 | msgid "" 4 | msgstr "" 5 | "Project-Id-Version: WhatsUpp\n" 6 | "Report-Msgid-Bugs-To: \n" 7 | "POT-Creation-Date: 2017-06-17 11:15+0200\n" 8 | "PO-Revision-Date: 2017-07-10 09:58+0100\n" 9 | "Last-Translator: void\n" 10 | "Language-Team: \n" 11 | "Language: en\n" 12 | "MIME-Version: 1.0\n" 13 | "Content-Type: text/plain; charset=UTF-8\n" 14 | "Content-Transfer-Encoding: 8bit\n" 15 | "X-Generator: Poedit 1.6.10\n" 16 | 17 | #: app/main.js:168 app/main.js:192 app/main.js:198 app/main.js:214 18 | msgid "Show" 19 | msgstr "Show" 20 | 21 | #: app/main.js:174 app/menu.js:146 app/main.js:198 app/menu.js:159 22 | #: app/main.js:204 app/main.js:220 23 | msgid "Hide" 24 | msgstr "Hide" 25 | 26 | #: app/main.js:181 app/menu.js:163 app/menu.js:191 app/main.js:205 27 | #: app/menu.js:176 app/menu.js:204 app/main.js:211 app/menu.js:197 28 | #: app/main.js:227 29 | msgid "Quit" 30 | msgstr "Quit" 31 | 32 | #: app/menu.js:6 33 | msgid "Edit" 34 | msgstr "Edit" 35 | 36 | #: app/menu.js:9 37 | msgid "Undo" 38 | msgstr "Undo" 39 | 40 | #: app/menu.js:14 41 | msgid "Redo" 42 | msgstr "Redo" 43 | 44 | #: app/menu.js:22 45 | msgid "Cut" 46 | msgstr "Cut" 47 | 48 | #: app/menu.js:27 49 | msgid "Copy" 50 | msgstr "Copy" 51 | 52 | #: app/menu.js:32 53 | msgid "Paste" 54 | msgstr "Paste" 55 | 56 | #: app/menu.js:37 57 | msgid "Select All" 58 | msgstr "Select All" 59 | 60 | #: app/menu.js:45 app/html/settings.html:20 61 | msgid "Settings" 62 | msgstr "Settings" 63 | 64 | #: app/menu.js:54 65 | msgid "View" 66 | msgstr "View" 67 | 68 | #: app/menu.js:57 69 | msgid "Reload" 70 | msgstr "Reload" 71 | 72 | #: app/menu.js:65 73 | msgid "Toggle Full Screen" 74 | msgstr "Toggle Full Screen" 75 | 76 | #: app/menu.js:78 77 | msgid "Toggle Developer Tools" 78 | msgstr "Toggle Developer Tools" 79 | 80 | #: app/menu.js:93 app/menu.js:106 81 | msgid "Window" 82 | msgstr "Window" 83 | 84 | #: app/menu.js:97 app/menu.js:110 85 | msgid "Minimize" 86 | msgstr "Minimize" 87 | 88 | #: app/menu.js:102 app/html/settings.html:56 app/menu.js:115 89 | #: app/html/settings.html:60 app/html/settings.html:64 90 | #: app/html/settings.html:68 91 | msgid "Close" 92 | msgstr "Close" 93 | 94 | #: app/menu.js:109 app/menu.js:122 95 | msgid "Audio" 96 | msgstr "Audio" 97 | 98 | #: app/menu.js:112 app/menu.js:125 99 | msgid "Increase Audio Rate by 20%" 100 | msgstr "Increase Audio Rate by 20%" 101 | 102 | #: app/menu.js:121 app/menu.js:134 103 | msgid "Decrease Audio Rate by 20%" 104 | msgstr "Decrease Audio Rate by 20%" 105 | 106 | #: app/menu.js:139 app/menu.js:184 app/menu.js:152 app/menu.js:197 107 | msgid "About" 108 | msgstr "About" 109 | 110 | #: app/menu.js:151 app/menu.js:164 111 | msgid "Hide Others" 112 | msgstr "Hide Others" 113 | 114 | #: app/menu.js:156 app/menu.js:169 115 | msgid "Show All" 116 | msgstr "Show All" 117 | 118 | #: app/menu.js:175 app/menu.js:188 119 | msgid "Bring All to Front" 120 | msgstr "Bring All to Front" 121 | 122 | #: app/html/settings.html:25 123 | msgid "Hide Avatars" 124 | msgstr "Hide Avatars" 125 | 126 | #: app/html/settings.html:29 127 | msgid "Hide Message Previews" 128 | msgstr "Hide Message Previews" 129 | 130 | #: app/html/settings.html:40 app/html/settings.html:44 131 | #: app/html/settings.html:48 app/html/settings.html:52 132 | msgid "Use Proxy (Changes in proxy settings require app restart)" 133 | msgstr "Use Proxy (Changes in proxy settings require app restart)" 134 | 135 | #: app/html/settings.html:50 app/html/settings.html:54 136 | #: app/html/settings.html:58 app/html/settings.html:62 137 | msgid "Https Proxy" 138 | msgstr "Https Proxy" 139 | 140 | #: app/html/settings.html:57 app/html/settings.html:61 141 | #: app/html/settings.html:65 app/html/settings.html:69 142 | msgid "Save" 143 | msgstr "Save" 144 | 145 | #: app/menu.js:91 146 | msgid "Phone info" 147 | msgstr "Phone info" 148 | 149 | #: app/html/settings.html:33 150 | msgid "Show Tray Icon" 151 | msgstr "Show Tray Icon" 152 | 153 | #: app/html/settings.html:37 154 | msgid "Minimize to tray on startup" 155 | msgstr "Minimize to tray on startup" 156 | 157 | #: app/html/settings.html:41 158 | msgid "Auto start on login" 159 | msgstr "Auto start on login" 160 | 161 | #~ msgid "Thumb Size" 162 | #~ msgstr "Thumb Size" 163 | -------------------------------------------------------------------------------- /app/locale/es_ES/messages.po: -------------------------------------------------------------------------------- 1 | # WhatsUpp translations. 2 | # 3 | msgid "" 4 | msgstr "" 5 | "Project-Id-Version: WhatsUpp\n" 6 | "Report-Msgid-Bugs-To: \n" 7 | "POT-Creation-Date: 2017-06-17 11:15+0200\n" 8 | "PO-Revision-Date: 2017-08-26 17:11-0300\n" 9 | "Language-Team: Mauricio López\n" 10 | "MIME-Version: 1.0\n" 11 | "Content-Type: text/plain; charset=UTF-8\n" 12 | "Content-Transfer-Encoding: 8bit\n" 13 | "X-Generator: Poedit 2.0.3\n" 14 | "Last-Translator: \n" 15 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 16 | "Language: es_419\n" 17 | 18 | #: app/main.js:168 app/main.js:192 app/main.js:198 app/main.js:214 19 | msgid "Show" 20 | msgstr "Mostrar" 21 | 22 | #: app/main.js:174 app/menu.js:146 app/main.js:198 app/menu.js:159 23 | #: app/main.js:204 app/main.js:220 24 | msgid "Hide" 25 | msgstr "Ocultar" 26 | 27 | #: app/main.js:181 app/menu.js:163 app/menu.js:191 app/main.js:205 28 | #: app/menu.js:176 app/menu.js:204 app/main.js:211 app/menu.js:197 29 | #: app/main.js:227 30 | msgid "Quit" 31 | msgstr "Salir" 32 | 33 | #: app/menu.js:6 34 | msgid "Edit" 35 | msgstr "Editar" 36 | 37 | #: app/menu.js:9 38 | msgid "Undo" 39 | msgstr "Deshacer" 40 | 41 | #: app/menu.js:14 42 | msgid "Redo" 43 | msgstr "Rehacer" 44 | 45 | #: app/menu.js:22 46 | msgid "Cut" 47 | msgstr "Cortar" 48 | 49 | #: app/menu.js:27 50 | msgid "Copy" 51 | msgstr "Copiar" 52 | 53 | #: app/menu.js:32 54 | msgid "Paste" 55 | msgstr "Pegar" 56 | 57 | #: app/menu.js:37 58 | msgid "Select All" 59 | msgstr "Seleccionar todo" 60 | 61 | #: app/menu.js:45 app/html/settings.html:20 62 | msgid "Settings" 63 | msgstr "Ajustes" 64 | 65 | #: app/menu.js:54 66 | msgid "View" 67 | msgstr "Ver" 68 | 69 | #: app/menu.js:57 70 | msgid "Reload" 71 | msgstr "Actualizar" 72 | 73 | #: app/menu.js:65 74 | msgid "Toggle Full Screen" 75 | msgstr "Alternar pantalla completa" 76 | 77 | #: app/menu.js:78 78 | msgid "Toggle Developer Tools" 79 | msgstr "Alternar herramientas de desarrollo" 80 | 81 | #: app/menu.js:93 app/menu.js:106 82 | msgid "Window" 83 | msgstr "Ventana" 84 | 85 | #: app/menu.js:97 app/menu.js:110 86 | msgid "Minimize" 87 | msgstr "Minimizar" 88 | 89 | #: app/menu.js:102 app/html/settings.html:56 app/menu.js:115 90 | #: app/html/settings.html:60 app/html/settings.html:64 91 | #: app/html/settings.html:68 92 | msgid "Close" 93 | msgstr "Cerrar" 94 | 95 | #: app/menu.js:109 app/menu.js:122 96 | msgid "Audio" 97 | msgstr "Audio" 98 | 99 | #: app/menu.js:112 app/menu.js:125 100 | msgid "Increase Audio Rate by 20%" 101 | msgstr "Subir volumen un 20%" 102 | 103 | #: app/menu.js:121 app/menu.js:134 104 | msgid "Decrease Audio Rate by 20%" 105 | msgstr "Bajar volumen un 20%" 106 | 107 | #: app/menu.js:139 app/menu.js:184 app/menu.js:152 app/menu.js:197 108 | msgid "About" 109 | msgstr "Acerca de" 110 | 111 | #: app/menu.js:151 app/menu.js:164 112 | msgid "Hide Others" 113 | msgstr "Ocultar otros" 114 | 115 | #: app/menu.js:156 app/menu.js:169 116 | msgid "Show All" 117 | msgstr "Mostrar todos" 118 | 119 | #: app/menu.js:175 app/menu.js:188 120 | msgid "Bring All to Front" 121 | msgstr "Traer todos al frente" 122 | 123 | #: app/html/settings.html:25 124 | msgid "Hide Avatars" 125 | msgstr "Ocultar avatares" 126 | 127 | #: app/html/settings.html:29 128 | msgid "Hide Message Previews" 129 | msgstr "Ocultar previsualización de mensajes" 130 | 131 | #: app/html/settings.html:40 app/html/settings.html:44 132 | #: app/html/settings.html:48 app/html/settings.html:52 133 | msgid "Use Proxy (Changes in proxy settings require app restart)" 134 | msgstr "Usar proxy (los cambios en los ajustes del proxy requieren reiniciar la aplicación)" 135 | 136 | #: app/html/settings.html:50 app/html/settings.html:54 137 | #: app/html/settings.html:58 app/html/settings.html:62 138 | msgid "Https Proxy" 139 | msgstr "Proxy https" 140 | 141 | #: app/html/settings.html:57 app/html/settings.html:61 142 | #: app/html/settings.html:65 app/html/settings.html:69 143 | msgid "Save" 144 | msgstr "Guardar" 145 | 146 | #: app/menu.js:91 147 | msgid "Phone info" 148 | msgstr "Información del teléfono" 149 | 150 | #: app/html/settings.html:33 151 | msgid "Show Tray Icon" 152 | msgstr "Mostrar ícono en la barra de notificación" 153 | 154 | #: app/html/settings.html:37 155 | msgid "Minimize to tray on startup" 156 | msgstr "Minimizar a la barra de notifiación al iniciar" 157 | 158 | #: app/html/settings.html:41 159 | msgid "Auto start on login" 160 | msgstr "Inicio automático al iniciar sesión" 161 | -------------------------------------------------------------------------------- /app/locale/it_IT/messages.po: -------------------------------------------------------------------------------- 1 | # WhatsUpp translations. 2 | # 3 | msgid "" 4 | msgstr "" 5 | "Project-Id-Version: WhatsUpp\n" 6 | "Report-Msgid-Bugs-To: \n" 7 | "POT-Creation-Date: 2017-06-17 11:15+0200\n" 8 | "PO-Revision-Date: 2017-07-10 09:59+0100\n" 9 | "Last-Translator: void\n" 10 | "Language-Team: \n" 11 | "Language: it\n" 12 | "MIME-Version: 1.0\n" 13 | "Content-Type: text/plain; charset=UTF-8\n" 14 | "Content-Transfer-Encoding: 8bit\n" 15 | "X-Generator: Poedit 1.6.10\n" 16 | 17 | #: app/main.js:168 app/main.js:192 app/main.js:198 app/main.js:214 18 | msgid "Show" 19 | msgstr "Visualizza" 20 | 21 | #: app/main.js:174 app/menu.js:146 app/main.js:198 app/menu.js:159 22 | #: app/main.js:204 app/main.js:220 23 | msgid "Hide" 24 | msgstr "Nascondi" 25 | 26 | #: app/main.js:181 app/menu.js:163 app/menu.js:191 app/main.js:205 27 | #: app/menu.js:176 app/menu.js:204 app/main.js:211 app/menu.js:197 28 | #: app/main.js:227 29 | msgid "Quit" 30 | msgstr "Esci" 31 | 32 | #: app/menu.js:6 33 | msgid "Edit" 34 | msgstr "Modifica" 35 | 36 | #: app/menu.js:9 37 | msgid "Undo" 38 | msgstr "Annulla" 39 | 40 | #: app/menu.js:14 41 | msgid "Redo" 42 | msgstr "Ripeti" 43 | 44 | #: app/menu.js:22 45 | msgid "Cut" 46 | msgstr "Taglia" 47 | 48 | #: app/menu.js:27 49 | msgid "Copy" 50 | msgstr "Copia" 51 | 52 | #: app/menu.js:32 53 | msgid "Paste" 54 | msgstr "Incolla" 55 | 56 | #: app/menu.js:37 57 | msgid "Select All" 58 | msgstr "Seleziona tutto" 59 | 60 | #: app/menu.js:45 app/html/settings.html:20 61 | msgid "Settings" 62 | msgstr "Impostazioni" 63 | 64 | #: app/menu.js:54 65 | msgid "View" 66 | msgstr "Vista" 67 | 68 | #: app/menu.js:57 69 | msgid "Reload" 70 | msgstr "Ricarica" 71 | 72 | #: app/menu.js:65 73 | msgid "Toggle Full Screen" 74 | msgstr "Attiva/disattiva schermo intero" 75 | 76 | #: app/menu.js:78 77 | msgid "Toggle Developer Tools" 78 | msgstr "Attiva/disattiva tool sviluppatori" 79 | 80 | #: app/menu.js:93 app/menu.js:106 81 | msgid "Window" 82 | msgstr "Finestra" 83 | 84 | #: app/menu.js:97 app/menu.js:110 85 | msgid "Minimize" 86 | msgstr "Minimizza" 87 | 88 | #: app/menu.js:102 app/html/settings.html:56 app/menu.js:115 89 | #: app/html/settings.html:60 app/html/settings.html:64 90 | #: app/html/settings.html:68 91 | msgid "Close" 92 | msgstr "Chiudi" 93 | 94 | #: app/menu.js:109 app/menu.js:122 95 | msgid "Audio" 96 | msgstr "Audio" 97 | 98 | #: app/menu.js:112 app/menu.js:125 99 | msgid "Increase Audio Rate by 20%" 100 | msgstr "Incrementa la velocità dell'audio del 20%" 101 | 102 | #: app/menu.js:121 app/menu.js:134 103 | msgid "Decrease Audio Rate by 20%" 104 | msgstr "Decrementa la velocità dell'audio del 20%" 105 | 106 | #: app/menu.js:139 app/menu.js:184 app/menu.js:152 app/menu.js:197 107 | msgid "About" 108 | msgstr "Riguardo a" 109 | 110 | #: app/menu.js:151 app/menu.js:164 111 | msgid "Hide Others" 112 | msgstr "Nascondi le altre" 113 | 114 | #: app/menu.js:156 app/menu.js:169 115 | msgid "Show All" 116 | msgstr "Visualizza tutto" 117 | 118 | #: app/menu.js:175 app/menu.js:188 119 | msgid "Bring All to Front" 120 | msgstr "Porta tutto in primo piano" 121 | 122 | #: app/html/settings.html:25 123 | msgid "Hide Avatars" 124 | msgstr "Nascondi gli avatars" 125 | 126 | #: app/html/settings.html:29 127 | msgid "Hide Message Previews" 128 | msgstr "Nascondi le anteprime dei messaggi" 129 | 130 | #: app/html/settings.html:40 app/html/settings.html:44 131 | #: app/html/settings.html:48 app/html/settings.html:52 132 | msgid "Use Proxy (Changes in proxy settings require app restart)" 133 | msgstr "Usa un proxy (è necessario un riavvio)" 134 | 135 | #: app/html/settings.html:50 app/html/settings.html:54 136 | #: app/html/settings.html:58 app/html/settings.html:62 137 | msgid "Https Proxy" 138 | msgstr "Proxy HTTPS" 139 | 140 | #: app/html/settings.html:57 app/html/settings.html:61 141 | #: app/html/settings.html:65 app/html/settings.html:69 142 | msgid "Save" 143 | msgstr "Salva" 144 | 145 | #: app/menu.js:91 146 | msgid "Phone info" 147 | msgstr "Informazioni telefono" 148 | 149 | #: app/html/settings.html:33 150 | msgid "Show Tray Icon" 151 | msgstr "Visualizza icona nel vassoio" 152 | 153 | #: app/html/settings.html:37 154 | msgid "Minimize to tray on startup" 155 | msgstr "Minimizza nel vassoio all'avvio" 156 | 157 | #: app/html/settings.html:41 158 | msgid "Auto start on login" 159 | msgstr "Avvia automaticamente all'accesso" 160 | 161 | #~ msgid "Thumb Size" 162 | #~ msgstr "Dimensione anteprima" 163 | -------------------------------------------------------------------------------- /app/locale/messages.pot: -------------------------------------------------------------------------------- 1 | # WhatsUpp translations. 2 | # 3 | msgid "" 4 | msgstr "" 5 | "Project-Id-Version: WhatsUpp\n" 6 | "Report-Msgid-Bugs-To: \n" 7 | "POT-Creation-Date: 2017-06-17 11:15+0200\n" 8 | "PO-Revision-Date: 2017-06-17 12:12+0100\n" 9 | "Last-Translator: void\n" 10 | "Language-Team: \n" 11 | "Language: en\n" 12 | "MIME-Version: 1.0\n" 13 | "Content-Type: text/plain; charset=UTF-8\n" 14 | "Content-Transfer-Encoding: 8bit\n" 15 | "X-Generator: Poedit 1.6.10\n" 16 | 17 | #: app/main.js:168 app/main.js:192 app/main.js:198 app/main.js:214 18 | msgid "Show" 19 | msgstr "" 20 | 21 | #: app/main.js:174 app/menu.js:146 app/main.js:198 app/menu.js:159 22 | #: app/main.js:204 app/main.js:220 23 | msgid "Hide" 24 | msgstr "" 25 | 26 | #: app/main.js:181 app/menu.js:163 app/menu.js:191 app/main.js:205 27 | #: app/menu.js:176 app/menu.js:204 app/main.js:211 app/menu.js:197 28 | #: app/main.js:227 29 | msgid "Quit" 30 | msgstr "" 31 | 32 | #: app/menu.js:6 33 | msgid "Edit" 34 | msgstr "" 35 | 36 | #: app/menu.js:9 37 | msgid "Undo" 38 | msgstr "" 39 | 40 | #: app/menu.js:14 41 | msgid "Redo" 42 | msgstr "" 43 | 44 | #: app/menu.js:22 45 | msgid "Cut" 46 | msgstr "" 47 | 48 | #: app/menu.js:27 49 | msgid "Copy" 50 | msgstr "" 51 | 52 | #: app/menu.js:32 53 | msgid "Paste" 54 | msgstr "" 55 | 56 | #: app/menu.js:37 57 | msgid "Select All" 58 | msgstr "" 59 | 60 | #: app/menu.js:45 app/html/settings.html:20 61 | msgid "Settings" 62 | msgstr "" 63 | 64 | #: app/menu.js:54 65 | msgid "View" 66 | msgstr "" 67 | 68 | #: app/menu.js:57 69 | msgid "Reload" 70 | msgstr "" 71 | 72 | #: app/menu.js:65 73 | msgid "Toggle Full Screen" 74 | msgstr "" 75 | 76 | #: app/menu.js:78 77 | msgid "Toggle Developer Tools" 78 | msgstr "" 79 | 80 | #: app/menu.js:93 app/menu.js:106 81 | msgid "Window" 82 | msgstr "" 83 | 84 | #: app/menu.js:97 app/menu.js:110 85 | msgid "Minimize" 86 | msgstr "" 87 | 88 | #: app/menu.js:102 app/html/settings.html:56 app/menu.js:115 89 | #: app/html/settings.html:60 app/html/settings.html:64 90 | #: app/html/settings.html:68 91 | msgid "Close" 92 | msgstr "" 93 | 94 | #: app/menu.js:109 app/menu.js:122 95 | msgid "Audio" 96 | msgstr "" 97 | 98 | #: app/menu.js:112 app/menu.js:125 99 | msgid "Increase Audio Rate by 20%" 100 | msgstr "" 101 | 102 | #: app/menu.js:121 app/menu.js:134 103 | msgid "Decrease Audio Rate by 20%" 104 | msgstr "" 105 | 106 | #: app/menu.js:139 app/menu.js:184 app/menu.js:152 app/menu.js:197 107 | msgid "About" 108 | msgstr "" 109 | 110 | #: app/menu.js:151 app/menu.js:164 111 | msgid "Hide Others" 112 | msgstr "" 113 | 114 | #: app/menu.js:156 app/menu.js:169 115 | msgid "Show All" 116 | msgstr "" 117 | 118 | #: app/menu.js:175 app/menu.js:188 119 | msgid "Bring All to Front" 120 | msgstr "" 121 | 122 | #: app/html/settings.html:25 123 | msgid "Hide Avatars" 124 | msgstr "" 125 | 126 | #: app/html/settings.html:29 127 | msgid "Hide Message Previews" 128 | msgstr "" 129 | 130 | #: app/html/settings.html:40 app/html/settings.html:44 131 | #: app/html/settings.html:48 app/html/settings.html:52 132 | msgid "Use Proxy (Changes in proxy settings require app restart)" 133 | msgstr "" 134 | 135 | #: app/html/settings.html:50 app/html/settings.html:54 136 | #: app/html/settings.html:58 app/html/settings.html:62 137 | msgid "Https Proxy" 138 | msgstr "" 139 | 140 | #: app/html/settings.html:57 app/html/settings.html:61 141 | #: app/html/settings.html:65 app/html/settings.html:69 142 | msgid "Save" 143 | msgstr "" 144 | 145 | #: app/menu.js:91 146 | msgid "Phone info" 147 | msgstr "" 148 | 149 | #: app/html/settings.html:33 150 | msgid "Show Tray Icon" 151 | msgstr "" 152 | 153 | #: app/html/settings.html:37 154 | msgid "Minimize to tray on startup" 155 | msgstr "" 156 | 157 | #: app/html/settings.html:41 158 | msgid "Auto start on login" 159 | msgstr "" 160 | -------------------------------------------------------------------------------- /app/locale/pt_BR/messages.po: -------------------------------------------------------------------------------- 1 | # WhatsUpp translations. 2 | # 3 | msgid "" 4 | msgstr "" 5 | "Project-Id-Version: WhatsUpp\n" 6 | "Report-Msgid-Bugs-To: \n" 7 | "POT-Creation-Date: 2017-08-05 17:02+0300\n" 8 | "PO-Revision-Date: 2017-08-05 17:02+0300\n" 9 | "Last-Translator: void\n" 10 | "Language-Team: \n" 11 | "Language: pt_br\n" 12 | "MIME-Version: 1.0\n" 13 | "Content-Type: text/plain; charset=UTF-8\n" 14 | "Content-Transfer-Encoding: 8bit\n" 15 | "X-Generator: Poedit 1.6.10\n" 16 | 17 | #: app/main.js:168 app/main.js:192 app/main.js:198 app/main.js:214 18 | msgid "Show" 19 | msgstr "Mostrar" 20 | 21 | #: app/main.js:174 app/menu.js:146 app/main.js:198 app/menu.js:159 22 | #: app/main.js:204 app/main.js:220 23 | msgid "Hide" 24 | msgstr "Ocultar" 25 | 26 | #: app/main.js:181 app/menu.js:163 app/menu.js:191 app/main.js:205 27 | #: app/menu.js:176 app/menu.js:204 app/main.js:211 app/menu.js:197 28 | #: app/main.js:227 29 | msgid "Quit" 30 | msgstr "Sair" 31 | 32 | #: app/menu.js:6 33 | msgid "Edit" 34 | msgstr "Editar" 35 | 36 | #: app/menu.js:9 37 | msgid "Undo" 38 | msgstr "Desfazer" 39 | 40 | #: app/menu.js:14 41 | msgid "Redo" 42 | msgstr "Refazer" 43 | 44 | #: app/menu.js:22 45 | msgid "Cut" 46 | msgstr "Cortar" 47 | 48 | #: app/menu.js:27 49 | msgid "Copy" 50 | msgstr "Copiar" 51 | 52 | #: app/menu.js:32 53 | msgid "Paste" 54 | msgstr "Colar" 55 | 56 | #: app/menu.js:37 57 | msgid "Select All" 58 | msgstr "Selecionar Tudo" 59 | 60 | #: app/menu.js:45 app/html/settings.html:20 61 | msgid "Settings" 62 | msgstr "Configurações" 63 | 64 | #: app/menu.js:54 65 | msgid "View" 66 | msgstr "Visualizar" 67 | 68 | #: app/menu.js:57 69 | msgid "Reload" 70 | msgstr "Recarregar" 71 | 72 | #: app/menu.js:65 73 | msgid "Toggle Full Screen" 74 | msgstr "Tela Cheia" 75 | 76 | #: app/menu.js:78 77 | msgid "Toggle Developer Tools" 78 | msgstr "Ferramentas de Desenvolvedor" 79 | 80 | #: app/menu.js:93 app/menu.js:106 81 | msgid "Window" 82 | msgstr "Janela" 83 | 84 | #: app/menu.js:97 app/menu.js:110 85 | msgid "Minimize" 86 | msgstr "Minimizar" 87 | 88 | #: app/menu.js:102 app/html/settings.html:56 app/menu.js:115 89 | #: app/html/settings.html:60 app/html/settings.html:64 90 | #: app/html/settings.html:68 91 | msgid "Close" 92 | msgstr "Fechar" 93 | 94 | #: app/menu.js:109 app/menu.js:122 95 | msgid "Audio" 96 | msgstr "Áudio" 97 | 98 | #: app/menu.js:112 app/menu.js:125 99 | msgid "Increase Audio Rate by 20%" 100 | msgstr "Aumentar Áudio em 20%" 101 | 102 | #: app/menu.js:121 app/menu.js:134 103 | msgid "Decrease Audio Rate by 20%" 104 | msgstr "Diminuir Áudio em 20%" 105 | 106 | #: app/menu.js:139 app/menu.js:184 app/menu.js:152 app/menu.js:197 107 | msgid "About" 108 | msgstr "Sobre" 109 | 110 | #: app/menu.js:151 app/menu.js:164 111 | msgid "Hide Others" 112 | msgstr "Esconder Outros" 113 | 114 | #: app/menu.js:156 app/menu.js:169 115 | msgid "Show All" 116 | msgstr "Mostrar Tudo" 117 | 118 | #: app/menu.js:175 app/menu.js:188 119 | msgid "Bring All to Front" 120 | msgstr "Trazer Tudo à Frente" 121 | 122 | #: app/html/settings.html:25 123 | msgid "Hide Avatars" 124 | msgstr "Ocultar Avatars" 125 | 126 | #: app/html/settings.html:29 127 | msgid "Hide Message Previews" 128 | msgstr "Ocultar Preview de Mensagens " 129 | 130 | #: app/html/settings.html:40 app/html/settings.html:44 131 | #: app/html/settings.html:48 app/html/settings.html:52 132 | msgid "Use Proxy (Changes in proxy settings require app restart)" 133 | msgstr "Usar Proxy (Mudanças no proxy requerem o reínicio do app)" 134 | 135 | #: app/html/settings.html:50 app/html/settings.html:54 136 | #: app/html/settings.html:58 app/html/settings.html:62 137 | msgid "Https Proxy" 138 | msgstr "Proxy Https" 139 | 140 | #: app/html/settings.html:57 app/html/settings.html:61 141 | #: app/html/settings.html:65 app/html/settings.html:69 142 | msgid "Save" 143 | msgstr "Salvar" 144 | 145 | #: app/menu.js:91 146 | msgid "Phone info" 147 | msgstr "Informações do Telefone" 148 | 149 | #: app/html/settings.html:33 150 | msgid "Show Tray Icon" 151 | msgstr "Mostrar Ícone na Bandeja" 152 | 153 | #: app/html/settings.html:37 154 | msgid "Minimize to tray on startup" 155 | msgstr "Minimizar para a bandeja ao iniciar" 156 | 157 | #: app/html/settings.html:41 158 | msgid "Auto start on login" 159 | msgstr "Auto iniciar no login" 160 | 161 | #~ msgid "Thumb Size" 162 | #~ msgstr "Tamanho da Miniatura" 163 | -------------------------------------------------------------------------------- /app/locale/ru_RU/messages.po: -------------------------------------------------------------------------------- 1 | # WhatsUpp translations. 2 | # 3 | msgid "" 4 | msgstr "" 5 | "Project-Id-Version: WhatsUpp\n" 6 | "Report-Msgid-Bugs-To: \n" 7 | "POT-Creation-Date: 2017-06-17 11:15+0200\n" 8 | "PO-Revision-Date: 2017-11-27 19:54+0300\n" 9 | "Last-Translator: void\n" 10 | "Language-Team: \n" 11 | "Language: ru\n" 12 | "MIME-Version: 1.0\n" 13 | "Content-Type: text/plain; charset=UTF-8\n" 14 | "Content-Transfer-Encoding: 8bit\n" 15 | "X-Generator: Poedit 1.5.4\n" 16 | 17 | #: app/main.js:168 app/main.js:192 app/main.js:198 app/main.js:214 18 | msgid "Show" 19 | msgstr "Восстановить" 20 | 21 | #: app/main.js:174 app/menu.js:146 app/main.js:198 app/menu.js:159 22 | #: app/main.js:204 app/main.js:220 23 | msgid "Hide" 24 | msgstr "Скрыть" 25 | 26 | #: app/main.js:181 app/menu.js:163 app/menu.js:191 app/main.js:205 27 | #: app/menu.js:176 app/menu.js:204 app/main.js:211 app/menu.js:197 28 | #: app/main.js:227 29 | msgid "Quit" 30 | msgstr "Выход" 31 | 32 | #: app/menu.js:6 33 | msgid "Edit" 34 | msgstr "Правка" 35 | 36 | #: app/menu.js:9 37 | msgid "Undo" 38 | msgstr "Отменить" 39 | 40 | #: app/menu.js:14 41 | msgid "Redo" 42 | msgstr "Вернуть" 43 | 44 | #: app/menu.js:22 45 | msgid "Cut" 46 | msgstr "Вырезать" 47 | 48 | #: app/menu.js:27 49 | msgid "Copy" 50 | msgstr "Копировать" 51 | 52 | #: app/menu.js:32 53 | msgid "Paste" 54 | msgstr "Вставить" 55 | 56 | #: app/menu.js:37 57 | msgid "Select All" 58 | msgstr "Выделить всё" 59 | 60 | #: app/menu.js:45 app/html/settings.html:20 61 | msgid "Settings" 62 | msgstr "Настройки" 63 | 64 | #: app/menu.js:54 65 | msgid "View" 66 | msgstr "Вид" 67 | 68 | #: app/menu.js:57 69 | msgid "Reload" 70 | msgstr "Перезагрузить" 71 | 72 | #: app/menu.js:65 73 | msgid "Toggle Full Screen" 74 | msgstr "Во весь экран" 75 | 76 | #: app/menu.js:78 77 | msgid "Toggle Developer Tools" 78 | msgstr "Инструменты разработчика" 79 | 80 | #: app/menu.js:93 app/menu.js:106 81 | msgid "Window" 82 | msgstr "Окно" 83 | 84 | #: app/menu.js:97 app/menu.js:110 85 | msgid "Minimize" 86 | msgstr "Свернуть" 87 | 88 | #: app/menu.js:102 app/html/settings.html:56 app/menu.js:115 89 | #: app/html/settings.html:60 app/html/settings.html:64 90 | #: app/html/settings.html:68 91 | msgid "Close" 92 | msgstr "Закрыть" 93 | 94 | #: app/menu.js:109 app/menu.js:122 95 | msgid "Audio" 96 | msgstr "Звук" 97 | 98 | #: app/menu.js:112 app/menu.js:125 99 | msgid "Increase Audio Rate by 20%" 100 | msgstr "Увеличить громкость на 20%" 101 | 102 | #: app/menu.js:121 app/menu.js:134 103 | msgid "Decrease Audio Rate by 20%" 104 | msgstr "Уменьшить громкость на 20%" 105 | 106 | #: app/menu.js:139 app/menu.js:184 app/menu.js:152 app/menu.js:197 107 | msgid "About" 108 | msgstr "О программе" 109 | 110 | #: app/menu.js:151 app/menu.js:164 111 | msgid "Hide Others" 112 | msgstr "Скрыть остальные" 113 | 114 | #: app/menu.js:156 app/menu.js:169 115 | msgid "Show All" 116 | msgstr "Показать все окна" 117 | 118 | #: app/menu.js:175 app/menu.js:188 119 | msgid "Bring All to Front" 120 | msgstr "Расположить сверху" 121 | 122 | #: app/html/settings.html:25 123 | msgid "Hide Avatars" 124 | msgstr "Скрывать аватарки" 125 | 126 | #: app/html/settings.html:29 127 | msgid "Hide Message Previews" 128 | msgstr "Скрывать содержимое сообщений" 129 | 130 | #: app/html/settings.html:40 app/html/settings.html:44 131 | #: app/html/settings.html:48 app/html/settings.html:52 132 | msgid "Use Proxy (Changes in proxy settings require app restart)" 133 | msgstr "Использовать Proxy (Требуется перезапуск программы)" 134 | 135 | #: app/html/settings.html:50 app/html/settings.html:54 136 | #: app/html/settings.html:58 app/html/settings.html:62 137 | msgid "Https Proxy" 138 | msgstr "Https Proxy" 139 | 140 | #: app/html/settings.html:57 app/html/settings.html:61 141 | #: app/html/settings.html:65 app/html/settings.html:69 142 | msgid "Save" 143 | msgstr "Сохранить" 144 | 145 | #: app/menu.js:91 146 | msgid "Phone info" 147 | msgstr "Информация о телефоне" 148 | 149 | #: app/html/settings.html:33 150 | msgid "Show Tray Icon" 151 | msgstr "Показывать иконку в трее" 152 | 153 | #: app/html/settings.html:37 154 | msgid "Minimize to tray on startup" 155 | msgstr "Свернуть в трей при запуске" 156 | 157 | #: app/html/settings.html:41 158 | msgid "Auto start on login" 159 | msgstr "Автозапуск" 160 | 161 | #~ msgid "Thumb Size" 162 | #~ msgstr "Размер изображения" 163 | -------------------------------------------------------------------------------- /app/locale/tr_TR/messages.po: -------------------------------------------------------------------------------- 1 | # WhatsUpp translations. 2 | # 3 | msgid "" 4 | msgstr "" 5 | "Project-Id-Version: WhatsUpp\n" 6 | "Report-Msgid-Bugs-To: \n" 7 | "POT-Creation-Date: 2018-01-23 19:25+0200\n" 8 | "PO-Revision-Date: 2018-01-23 19:30+0300\n" 9 | "Last-Translator: Demiray Muhterem \n" 10 | "Language-Team: Demiray Muhterem \n" 11 | "Language: tr_TR\n" 12 | "MIME-Version: 1.0\n" 13 | "Content-Type: text/plain; charset=UTF-8\n" 14 | "Content-Transfer-Encoding: 8bit\n" 15 | "X-Generator: Poedit 2.0.6\n" 16 | 17 | #: app/main.js:168 app/main.js:192 app/main.js:198 app/main.js:214 18 | msgid "Show" 19 | msgstr "Göster" 20 | 21 | #: app/main.js:174 app/menu.js:146 app/main.js:198 app/menu.js:159 22 | #: app/main.js:204 app/main.js:220 23 | msgid "Hide" 24 | msgstr "Gizle" 25 | 26 | #: app/main.js:181 app/menu.js:163 app/menu.js:191 app/main.js:205 27 | #: app/menu.js:176 app/menu.js:204 app/main.js:211 app/menu.js:197 28 | #: app/main.js:227 29 | msgid "Quit" 30 | msgstr "Çıkış" 31 | 32 | #: app/menu.js:6 33 | msgid "Edit" 34 | msgstr "Düzenle" 35 | 36 | #: app/menu.js:9 37 | msgid "Undo" 38 | msgstr "Geri Al" 39 | 40 | #: app/menu.js:14 41 | msgid "Redo" 42 | msgstr "Yenile" 43 | 44 | #: app/menu.js:22 45 | msgid "Cut" 46 | msgstr "Kes" 47 | 48 | #: app/menu.js:27 49 | msgid "Copy" 50 | msgstr "Kopyala" 51 | 52 | #: app/menu.js:32 53 | msgid "Paste" 54 | msgstr "Yapıştır" 55 | 56 | #: app/menu.js:37 57 | msgid "Select All" 58 | msgstr "Tümünü Seç" 59 | 60 | #: app/menu.js:45 app/html/settings.html:20 61 | msgid "Settings" 62 | msgstr "Ayarlar" 63 | 64 | #: app/menu.js:54 65 | msgid "View" 66 | msgstr "Görünüm" 67 | 68 | #: app/menu.js:57 69 | msgid "Reload" 70 | msgstr "Tekrar Yükle" 71 | 72 | #: app/menu.js:65 73 | msgid "Toggle Full Screen" 74 | msgstr "Tam Ekran" 75 | 76 | #: app/menu.js:78 77 | msgid "Toggle Developer Tools" 78 | msgstr "Geliştirici Araçları" 79 | 80 | #: app/menu.js:93 app/menu.js:106 81 | msgid "Window" 82 | msgstr "Pencere" 83 | 84 | #: app/menu.js:97 app/menu.js:110 85 | msgid "Minimize" 86 | msgstr "Küçült" 87 | 88 | #: app/menu.js:102 app/html/settings.html:56 app/menu.js:115 89 | #: app/html/settings.html:60 app/html/settings.html:64 90 | #: app/html/settings.html:68 91 | msgid "Close" 92 | msgstr "Kapat" 93 | 94 | #: app/menu.js:109 app/menu.js:122 95 | msgid "Audio" 96 | msgstr "Ses" 97 | 98 | #: app/menu.js:112 app/menu.js:125 99 | msgid "Increase Audio Rate by 20%" 100 | msgstr "Ses Oranını %20 Arttır" 101 | 102 | #: app/menu.js:121 app/menu.js:134 103 | msgid "Decrease Audio Rate by 20%" 104 | msgstr "Ses Oranını %20 Azalt" 105 | 106 | #: app/menu.js:139 app/menu.js:184 app/menu.js:152 app/menu.js:197 107 | msgid "About" 108 | msgstr "Hakkında" 109 | 110 | #: app/menu.js:151 app/menu.js:164 111 | msgid "Hide Others" 112 | msgstr "Diğerlerini Gizle" 113 | 114 | #: app/menu.js:156 app/menu.js:169 115 | msgid "Show All" 116 | msgstr "Tümünü Göster" 117 | 118 | #: app/menu.js:175 app/menu.js:188 119 | msgid "Bring All to Front" 120 | msgstr "Herşeyi Öne Çıkar" 121 | 122 | #: app/html/settings.html:25 123 | msgid "Hide Avatars" 124 | msgstr "Avatarları Gizle" 125 | 126 | #: app/html/settings.html:29 127 | msgid "Hide Message Previews" 128 | msgstr "Özel Mesajları Gizle" 129 | 130 | #: app/html/settings.html:40 app/html/settings.html:44 131 | #: app/html/settings.html:48 app/html/settings.html:52 132 | msgid "Use Proxy (Changes in proxy settings require app restart)" 133 | msgstr "Proxy Kullan (Uygulamayı yeniden başlatmayı gerektirir)" 134 | 135 | #: app/html/settings.html:50 app/html/settings.html:54 136 | #: app/html/settings.html:58 app/html/settings.html:62 137 | msgid "Https Proxy" 138 | msgstr "Https Proxy" 139 | 140 | #: app/html/settings.html:57 app/html/settings.html:61 141 | #: app/html/settings.html:65 app/html/settings.html:69 142 | msgid "Save" 143 | msgstr "Kaydet" 144 | 145 | #: app/menu.js:91 146 | msgid "Phone info" 147 | msgstr "Telefon Bilgisi" 148 | 149 | #: app/html/settings.html:33 150 | msgid "Show Tray Icon" 151 | msgstr "Sistem Çubuğunda Göster" 152 | 153 | #: app/html/settings.html:37 154 | msgid "Minimize to tray on startup" 155 | msgstr "Başlangıçta sistem çubuğuna küçült" 156 | 157 | #: app/html/settings.html:41 158 | msgid "Auto start on login" 159 | msgstr "Girişte otomatik başlat" 160 | -------------------------------------------------------------------------------- /app/main.js: -------------------------------------------------------------------------------- 1 | // vim: set ts=2 sw=2 expandtab: 2 | 3 | /* global _, whatsUpp, gt, config, settings, onlyWin, onlyLinux, onlyOSX, about, phoneinfo, autolauncher */ 4 | 5 | /* 6 | eslint new-cap: 7 | ["error", { 8 | "newIsCapExceptions": ["parseFloat", "Buffer.from"], 9 | "capIsNewExceptions": ["ContextMenu"] 10 | }] 11 | */ 12 | 13 | (function (scope) { 14 | 'use strict' 15 | 16 | const app = require('electron').app 17 | const AppMenu = require('electron').Menu 18 | const MenuItem = require('electron').MenuItem 19 | const AppTray = require('electron').Tray 20 | const fileSystem = require('fs-extra') 21 | const NativeImage = require('electron').nativeImage 22 | const BrowserWindow = require('electron').BrowserWindow 23 | const NodeGettext = require('node-gettext') 24 | const gettextParser = require('gettext-parser') 25 | const AutoLaunch = require('auto-launch') 26 | const log = require('electron-log') 27 | const join = require('path').join 28 | const request = require('request') 29 | const pjson = require('./package.json') 30 | const notifier = require('node-notifier') 31 | const globalShortcut = require('electron').globalShortcut 32 | const ContextMenu = require('electron-context-menu') 33 | const find = require('find') 34 | const pathBasename = require('path').basename 35 | const pathDirname = require('path').dirname 36 | const AppSession = require('electron').session 37 | const isPrimaryInstance = app.requestSingleInstanceLock() 38 | 39 | app.on('second-instance', (event, argv, cwd) => { 40 | if (whatsUpp.window) { 41 | if (whatsUpp.window.isMinimized()) { 42 | whatsUpp.window.restore() 43 | } 44 | whatsUpp.window.show() 45 | } 46 | 47 | let groupLinkOpenRequested = null 48 | if (argv.length > 1) { 49 | for (let i = 0; i < argv.length; i++) { 50 | if (argv[i].indexOf('https://chat.whatsapp.com') >= 0) { 51 | groupLinkOpenRequested = argv[i] 52 | log.info('Opening a group link: ' + groupLinkOpenRequested) 53 | break 54 | } 55 | } 56 | } 57 | if (groupLinkOpenRequested != null) { 58 | whatsUpp.window.webContents.executeJavaScript( 59 | "var el = document.createElement('a');" + 60 | 'el.href = "' + groupLinkOpenRequested + '";' + 61 | 'el.style.display = "none";' + 62 | "el.rel = 'noopener noreferrer';" + 63 | "el.id = 'newlink';" + 64 | 'document.body.appendChild(el);' + 65 | "setTimeout(function() { var el = document.getElementById('newlink'); el.click(); document.body.removeChild(el); }, 500);" 66 | ) 67 | } 68 | }) 69 | 70 | if (!isPrimaryInstance) { 71 | log.warn('App is already running. Quit.') 72 | app.quit() 73 | } 74 | 75 | app.setAppUserModelId('eu.alindt.whatsupp') 76 | app.setAsDefaultProtocolClient('whatsapp') 77 | 78 | if (process.argv.indexOf('--debug-log') >= 0) { 79 | log.transports.file.level = 'debug' 80 | log.info('Log level set from command line switch') 81 | } 82 | 83 | if (process.argv.indexOf('--disable-gpu') >= 0) { 84 | log.warn('Disabling GPU acceleration') 85 | app.disableHardwareAcceleration() 86 | } 87 | 88 | log.info('Log init, file ' + app.getPath('userData') + '/log.log') 89 | 90 | let groupLinkOpenRequested = null 91 | if (process.argv.length > 1) { 92 | for (let i = 0; i < process.argv.length; i++) { 93 | if (process.argv[i].indexOf('https://chat.whatsapp.com') >= 0) { 94 | groupLinkOpenRequested = process.argv[i] 95 | log.info('Opening a group link: ' + groupLinkOpenRequested) 96 | break 97 | } 98 | } 99 | } 100 | 101 | global.gt = new NodeGettext() 102 | 103 | const supportedLocales = [] 104 | const localePaths = find.fileSync('messages.po', join(__dirname, 'locale')) 105 | 106 | localePaths.forEach( 107 | function (localePath) { 108 | const localeName = pathBasename(pathDirname(localePath)) 109 | // log.debug('Loading locale ' + localeName + ' (' + localePath + ')') 110 | try { 111 | gt.addTranslations(localeName, 'messages', gettextParser.po.parse(fileSystem.readFileSync(localePath))) 112 | supportedLocales.push(localeName) 113 | } catch (err) { 114 | log.error(err.message) 115 | log.warn('Skipping locale ' + localeName + ' (' + localePath + ')') 116 | } 117 | }) 118 | 119 | log.info('Supported locales: ' + supportedLocales) 120 | 121 | gt.setTextDomain('messages') 122 | global._ = function (t) { 123 | return gt.gettext(t) 124 | } 125 | 126 | // Setting default language to system language if available 127 | const syslang = (process.env.LC_ALL !== undefined 128 | ? process.env.LC_ALL 129 | : (process.env.LANG !== undefined 130 | ? process.env.LANG 131 | : (process.env.LC_MESSAGES !== undefined ? process.env.LC_MESSAGES : 'en-US'))) 132 | 133 | if (supportedLocales.indexOf(syslang.split('.')[0]) >= 0) { 134 | log.info('Setting locale ' + syslang.split('.')[0]) 135 | gt.setLocale(syslang.split('.')[0]) 136 | } else { 137 | log.warn('No supported locale found, defaulting to en_US') 138 | gt.setLocale('en_US') 139 | } 140 | 141 | global.autolauncher = new AutoLaunch({ name: app.getName() }) 142 | 143 | global.onlyOSX = function (callback) { 144 | if (process.platform === 'darwin') { 145 | return Function.bind.apply(callback, this, [].slice.call(arguments, 0)) 146 | } 147 | return function () {} 148 | } 149 | 150 | global.onlyLinux = function (callback) { 151 | if (process.platform === 'linux') { 152 | return Function.bind.apply(callback, this, [].slice.call(arguments, 0)) 153 | } 154 | return function () {} 155 | } 156 | 157 | global.onlyWin = function (callback) { 158 | if (process.platform === 'win32' || process.platform === 'win64') { 159 | return Function.bind.apply(callback, this, [].slice.call(arguments, 0)) 160 | } 161 | return function () {} 162 | } 163 | 164 | global.config = { 165 | defaultSettings: { 166 | width: 1000, 167 | height: 720, 168 | thumbSize: 0 169 | }, 170 | 171 | currentSettings: {}, 172 | 173 | init () { 174 | config.loadConfiguration() 175 | config.saveTimeout = null 176 | }, 177 | 178 | loadConfiguration () { 179 | log.info('Loading configuration') 180 | const settingsFile = app.getPath('userData') + '/settings.json' 181 | try { 182 | const data = fileSystem.readFileSync(settingsFile) 183 | if (data !== '' && data !== '{}' && data !== '[]') { 184 | config.currentSettings = JSON.parse(data) 185 | log.info('Configuration loaded from ' + settingsFile) 186 | } else { 187 | config.currentSettings = config.defaultSettings 188 | log.warn('Configuration file empty, loading default') 189 | } 190 | } catch (e) { 191 | config.currentSettings = config.defaultSettings 192 | log.warn('Error loading configuration from ' + settingsFile + ' (' + e + '), loading default') 193 | } 194 | // First time configuration - eg. before app init 195 | if (config.get('disablegpu') === true) { 196 | log.warn('Disabling GPU acceleration') 197 | app.disableHardwareAcceleration() 198 | } 199 | }, 200 | 201 | applyConfiguration () { 202 | log.info('Applying configuration') 203 | if (config.get('maximized') && config.get('startminimized') !== true) { 204 | whatsUpp.window.maximize() 205 | } 206 | whatsUpp.window.webContents.on('dom-ready', function (event, two) { 207 | let fontSize = config.get('fontSize') 208 | fontSize = (fontSize === undefined) ? 'normal' : fontSize 209 | const fontCSS = (fontSize !== 'normal') ? 'font-size:' + fontSize + ' !important;' : '' 210 | this.insertCSS('* { text-rendering: optimizeSpeed !important; -webkit-font-smoothing: subpixel-antialiased !important; ' + 211 | fontCSS + '}') 212 | 213 | const imgpath = config.get('background-image') 214 | if (imgpath !== undefined) { 215 | // var img = new Buffer(fileSystem.readFileSync(imgpath)).toString('base64') 216 | const img = new Buffer.from(fileSystem.readFileSync(imgpath)).toString('base64') 217 | const opacity = parseFloat(config.get('background-opacity')) / 100.0 218 | const mime = (imgpath.endsWith('.jpg') || imgpath.endsWith('.jpeg')) 219 | ? 'image/jpg' 220 | : ((imgpath.endsWith('.png') ? 'image/png' : ((imgpath.endsWith('.gif') ? 'image/gif' : '')))) 221 | this.insertCSS('.pane-chat-tile { background-image: url(data:' + mime + ';base64,' + img + ') !important; background-size: cover !important; opacity: ' + 222 | opacity + ' !important; max-width: 100% !important; }') 223 | } 224 | 225 | const noAvatar = 'div#pane-side img[draggable="false"] { display: none !important; }' 226 | const noPreview = 'div > div > span[title] > span { display: none !important; }' 227 | 228 | // var noWAupdate = 'header + span > div > div > div > span[data-icon="alert-update] { display: none !important; }' 229 | const noWAupdate = 'div#side > span { display: none !important; }' 230 | this.insertCSS(noWAupdate) 231 | 232 | const thumbSize = '.image-thumb { width: ' + config.currentSettings.thumbSize + 'px !important;' + 233 | 'height: ' + config.currentSettings.thumbSize + 'px !important;}' + 234 | '.image-thumb img.image-thumb-body { width: auto !important;' + 235 | 'height: ' + config.currentSettings.thumbSize + 'px !important;}' 236 | 237 | const darkMode = '#pane-side, #pane-side div div div div div div, #side header, #side header div div' + 238 | '#side div, #side div div, #side div div button, #side div div label, #side div div input,' + 239 | '#main footer, #main footer div, #main footer div div, #main header, #main header div div span,' + 240 | '#main header div div div span' + 241 | '{ background-color: #2E2C2B !important; color: white; }\n' + 242 | '.message-in { background-color: #75706E !important; }\n' + 243 | '.message, .media-caption { color: #F0F0F0; }\n' + 244 | '.message-in .tail-container, .message-in.tail-override-right .tail-container,' + 245 | '.message-out.tail-override-right .tail-container, .message-in.tail-override-left' + 246 | '.tail-container { background-image: none !important; }\n' + 247 | '.block-compose, .block-compose .input-container { background-color: #2E2C2B !important; }\n' + 248 | '.pane-chat-header, .chat.active, .chat, .chatlist-panel-search, .pane-header.pane-list-header,' + 249 | '.input-chatlist-search, .chatlist-panel-body, .chatlist-panel-search div label input,' + 250 | '.chatlist-panel-search div label, #app > div > div > div._3q4NP._1Iexl > div, .message > div > span' + 251 | ' { background-color: #2E2C2B !important;, background-image: none !important; }\n' + 252 | '.chat-title, .header-title, .chat-body div span { color: white; }' 253 | 254 | const blurImages = 'div.message-in img, div.message-out img { filter: contrast(25%) blur(8px) grayscale(75%); } \n' + 255 | 'div.message-in:hover img, div.message-out:hover img { filter: none; }' 256 | 257 | if (config.currentSettings.hideAvatars) { 258 | this.insertCSS(noAvatar) 259 | } 260 | if (config.currentSettings.hidePreviews) { 261 | this.insertCSS(noPreview) 262 | } 263 | if (config.currentSettings.darkMode) { 264 | this.insertCSS(darkMode) 265 | } 266 | if (config.currentSettings.blurImages) { 267 | this.insertCSS(blurImages) 268 | } 269 | 270 | if (config.currentSettings.thumbSize) { 271 | this.insertCSS(thumbSize) 272 | } 273 | if (config.get('customcss') !== undefined) { 274 | try { 275 | this.insertCSS(fileSystem.readFileSync(config.get('customcss'), 'utf-8')) 276 | log.info('Loaded CSS file: ' + config.get('customcss')) 277 | } catch (e) { 278 | log.error('CSS error: ' + e) 279 | } 280 | } 281 | }) 282 | 283 | // OSX Dock menu 284 | if (process.platform === 'darwin') { 285 | const dockMenu = AppMenu.buildFromTemplate([ 286 | { 287 | label: 'Show main window', 288 | click () { 289 | whatsUpp.window.show() 290 | whatsUpp.window.setAlwaysOnTop(true) 291 | whatsUpp.window.focus() 292 | whatsUpp.window.setAlwaysOnTop(false) 293 | } 294 | } 295 | ]) 296 | app.dock.setMenu(dockMenu) 297 | app.on('activate', (event, hasVisibleWindows) => { 298 | whatsUpp.window.show() 299 | whatsUpp.window.setAlwaysOnTop(true) 300 | whatsUpp.window.focus() 301 | whatsUpp.window.setAlwaysOnTop(false) 302 | }) 303 | } 304 | 305 | if (config.get('trayicon') !== false && whatsUpp.tray === undefined) { 306 | whatsUpp.createTray() 307 | } else if (config.get('trayicon') === false && whatsUpp.tray !== undefined) { 308 | log.info('Destroying tray icon') 309 | whatsUpp.tray.destroy() 310 | whatsUpp.tray = undefined 311 | } 312 | if (config.get('autostart') === true) { 313 | autolauncher.isEnabled().then(function (enabled) { 314 | if (!enabled) { 315 | autolauncher.enable() 316 | log.info('Autostart enabled') 317 | } 318 | }) 319 | } else { 320 | autolauncher.isEnabled().then(function (enabled) { 321 | if (enabled) { 322 | autolauncher.disable() 323 | log.info('Autostart disabled') 324 | } 325 | }) 326 | } 327 | whatsUpp.window.setMenuBarVisibility(config.get('autoHideMenuBar') !== true) 328 | whatsUpp.window.setAutoHideMenuBar(config.get('autoHideMenuBar') === true) 329 | 330 | if (config.get('escCloseMainWindow')) { 331 | globalShortcut.register('Esc', () => { 332 | whatsUpp.window.close() 333 | }) 334 | } else { 335 | if (globalShortcut.isRegistered('Esc')) { 336 | globalShortcut.unregister('Esc') 337 | } 338 | } 339 | }, 340 | 341 | saveConfiguration () { 342 | if (config.saveTimeout != null) { 343 | clearTimeout(config.saveTimeout) 344 | config.saveTimeout = null 345 | } 346 | config.saveTimeout = setTimeout(function () { 347 | log.info('Saving configuration') 348 | config.set('maximized', whatsUpp.window.isMaximized()) 349 | if (config.currentSettings === undefined || JSON.stringify(config.currentSettings) === '') { 350 | // TODO: if we land here, we need to figure why and how. And fix that 351 | log.error('Configuration empty! This should not happen!') 352 | return 353 | } 354 | fileSystem.writeFileSync(app.getPath('userData') + '/settings.json', JSON.stringify(config.currentSettings, null, 2), 'utf-8') 355 | config.saveTimeout = null 356 | }, 2000) 357 | }, 358 | 359 | get (key) { 360 | return config.currentSettings[key] 361 | }, 362 | 363 | set (key, value) { 364 | config.currentSettings[key] = value 365 | }, 366 | 367 | unSet (key) { 368 | if (config.currentSettings.hasOwnProperty(key)) { 369 | delete config.currentSettings[key] 370 | } 371 | } 372 | } 373 | 374 | global.config.init() 375 | 376 | global.whatsUpp = { 377 | init () { 378 | global.whatsUpp.warningIcon = false 379 | whatsUpp.tray = undefined 380 | whatsUpp.createMenu() 381 | // Bitmask: LSB 382 | // First bit: warning icon (phone disconnected) 383 | // Second bit: new message red-dot 384 | global.whatsUpp.iconStatus = 0 385 | global.whatsUpp.oldIconStatus = 0 386 | global.whatsUpp.newVersion = null 387 | 388 | whatsUpp.clearCache() 389 | whatsUpp.openWindow() 390 | config.applyConfiguration() 391 | }, 392 | 393 | createMenu () { 394 | log.info('Creating menu') 395 | whatsUpp.menu = 396 | AppMenu.buildFromTemplate(require('./menu')) 397 | AppMenu.setApplicationMenu(whatsUpp.menu) 398 | }, 399 | 400 | setNormalTray () { 401 | global.whatsUpp.iconStatus = global.whatsUpp.iconStatus & 0xFFFFFFFE 402 | global.whatsUpp.updateTrayIcon() 403 | }, 404 | 405 | setWarningTray () { 406 | global.whatsUpp.iconStatus = global.whatsUpp.iconStatus | 0x00000001 407 | global.whatsUpp.updateTrayIcon() 408 | }, 409 | 410 | isWarningTrayIcon () { 411 | return (global.whatsUpp.iconStatus & 0x1) > 0 412 | }, 413 | 414 | setNewMessageIcon () { 415 | global.whatsUpp.iconStatus = global.whatsUpp.iconStatus | 0x00000002 416 | global.whatsUpp.updateTrayIcon() 417 | }, 418 | 419 | clearNewMessageIcon () { 420 | global.whatsUpp.iconStatus = global.whatsUpp.iconStatus & 0xFFFFFFFD 421 | global.whatsUpp.updateTrayIcon() 422 | }, 423 | 424 | isNewMessageIcon () { 425 | return (global.whatsUpp.iconStatus & 0x2) > 0 426 | }, 427 | 428 | updateTrayIcon () { 429 | if (global.whatsUpp.oldIconStatus === global.whatsUpp.iconStatus) { 430 | return 431 | } 432 | if (whatsUpp.tray !== undefined && process.platform !== 'darwin') { 433 | if (global.whatsUpp.isWarningTrayIcon() && !global.whatsUpp.isNewMessageIcon()) { 434 | log.info('Setting tray icon to warning') 435 | // whatsUpp.tray.setImage(__dirname + '/assets/icon/iconWarning.png') 436 | whatsUpp.tray.setImage(join(__dirname, 'assets', 'icon', 'iconWarning.png')) 437 | } if (global.whatsUpp.isWarningTrayIcon() && global.whatsUpp.isNewMessageIcon()) { 438 | log.info('Setting tray icon to warning with messages') 439 | // whatsUpp.tray.setImage(__dirname + '/assets/icon/iconWarningWithMsg.png') 440 | whatsUpp.tray.setImage(join(__dirname, 'assets', 'icon', 'iconWarningWithMsg.png')) 441 | } if (!global.whatsUpp.isWarningTrayIcon() && global.whatsUpp.isNewMessageIcon()) { 442 | log.info('Setting tray icon to normal with messages') 443 | // whatsUpp.tray.setImage(__dirname + '/assets/icon/iconWithMsg.png') 444 | whatsUpp.tray.setImage(join(__dirname, 'assets', 'icon', 'iconWithMsg.png')) 445 | } else { 446 | log.info('Setting tray icon to normal') 447 | // whatsUpp.tray.setImage(__dirname + '/assets/icon/icon.png') 448 | whatsUpp.tray.setImage(join(__dirname, 'assets', 'icon', 'icon.png')) 449 | } 450 | log.info('Mask value: ' + global.whatsUpp.iconStatus) 451 | } 452 | global.whatsUpp.oldIconStatus = global.whatsUpp.iconStatus 453 | }, 454 | 455 | createTray () { 456 | log.info('Creating tray icon') 457 | // var trayImg = __dirname + '/assets/img/trayTemplate.png' 458 | let trayImg = join(__dirname, 'assets', 'img', 'trayTemplate.png') 459 | // Darwin requires black/white/transparent icon, other platforms does not 460 | if (process.platform !== 'darwin') { 461 | // trayImg = __dirname + '/assets/icon/icon.png' 462 | trayImg = join(__dirname, 'assets', 'icon', 'icon.png') 463 | } 464 | whatsUpp.tray = new AppTray(trayImg) 465 | 466 | // Setting up a trayicon context menu 467 | whatsUpp.trayContextMenu = AppMenu.buildFromTemplate([ 468 | { 469 | label: _('Show'), 470 | visible: config.get('startminimized'), // Hide this option on start 471 | click: function () { 472 | whatsUpp.window.show() 473 | whatsUpp.window.setAlwaysOnTop(true) 474 | whatsUpp.window.focus() 475 | whatsUpp.window.setAlwaysOnTop(false) 476 | } 477 | }, 478 | 479 | { 480 | label: _('Hide'), 481 | visible: !config.get('startminimized'), // Show this option on start 482 | click: function () { 483 | whatsUpp.window.hide() 484 | } 485 | }, 486 | 487 | // Quit WhatsUpp 488 | { 489 | label: _('Quit'), 490 | click: function () { 491 | app.quit() 492 | } 493 | } 494 | ]) 495 | whatsUpp.tray.setContextMenu(whatsUpp.trayContextMenu) 496 | 497 | // Normal this will show the main window, but electron under Linux 498 | // dosent work with the clicked event so we are using the above 499 | // contextmenu insted - Rightclick the trayicon and pick Show 500 | // WhatsUpp 501 | // More info: 502 | // https://github.com/electron/electron/blob/master/docs/api/tray.md 503 | // See the Platform limitations section. 504 | whatsUpp.tray.on('clicked', () => { 505 | whatsUpp.window.show() 506 | whatsUpp.window.setAlwaysOnTop(true) 507 | whatsUpp.window.focus() 508 | whatsUpp.window.setAlwaysOnTop(false) 509 | }) 510 | whatsUpp.tray.on('click', () => { 511 | whatsUpp.window.show() 512 | whatsUpp.window.setAlwaysOnTop(true) 513 | whatsUpp.window.focus() 514 | whatsUpp.window.setAlwaysOnTop(false) 515 | }) 516 | 517 | whatsUpp.tray.setToolTip('WhatsUpp') 518 | }, 519 | 520 | clearCache () { 521 | log.info('Clearing cache') 522 | try { 523 | // fileSystem.unlinkSync(app.getPath('userData') + '/Application Cache/Index'); 524 | fileSystem.removeSync(app.getPath('userData') + '/Service Worker/') 525 | } catch (e) { 526 | log.warn('Error clearing cache: ' + e) 527 | } 528 | }, 529 | 530 | openWindow () { 531 | log.info('Open main window') 532 | whatsUpp.window = new BrowserWindow({ 533 | y: config.get('posY'), 534 | x: config.get('posX'), 535 | width: config.get('width'), 536 | height: config.get('height'), 537 | minWidth: 600, 538 | minHeight: 600, 539 | // "type": "toolbar", 540 | title: 'WhatsUpp', 541 | show: false, 542 | autoHideMenuBar: config.get('autoHideMenuBar') === true, 543 | // 'icon': __dirname + '/assets/icon/icon.png', 544 | icon: join(__dirname, 'assets', 'icon', 'icon.png'), 545 | webPreferences: { 546 | nodeIntegration: false, 547 | preload: join(__dirname, 'js', 'injected.js') 548 | } 549 | }) 550 | 551 | ContextMenu({ 552 | window: whatsUpp.window 553 | }) 554 | 555 | whatsUpp.window.loadURL('https://web.whatsapp.com') 556 | 557 | whatsUpp.window.webContents.on('did-finish-load', function () { 558 | if (groupLinkOpenRequested != null) { 559 | whatsUpp.window.webContents.executeJavaScript( 560 | "var el = document.createElement('a');" + 561 | 'el.href = "' + groupLinkOpenRequested + '";' + 562 | 'el.style.display = "none";' + 563 | "el.rel = 'noopener noreferrer';" + 564 | "el.id = 'newlink';" + 565 | 'document.body.appendChild(el);' + 566 | "setTimeout(function() { var el = document.getElementById('newlink'); el.click(); document.body.removeChild(el); }, 500);" 567 | ) 568 | } 569 | // Checking for new version 570 | const ep = pjson.releases 571 | log.info('Checking for new versions (current version ' + pjson.version + ')') 572 | const ua = AppSession.defaultSession.getUserAgent() 573 | request.get({ url: ep, headers: { 'User-Agent': ua } }, function (err, response, body) { 574 | if (!err && response !== undefined && response.statusCode === 200) { 575 | const ghinfo = JSON.parse(body) 576 | const versions = [] 577 | let verregexp = null 578 | 579 | if (pjson.reltype === 'stable') { 580 | verregexp = /^\d+\.\d+\.\d+/ 581 | } else if (pjson.reltype === 'dev') { 582 | verregexp = /^\d{8,}/ 583 | } 584 | 585 | for (let kk = 0; kk < ghinfo.length; kk++) { 586 | if (ghinfo[kk].name.match(verregexp)) { 587 | versions.push(ghinfo[kk].name) 588 | } 589 | } 590 | 591 | if (!versions.length) { versions.push('') } 592 | global.whatsUpp.newVersion = versions[0] 593 | if (whatsUpp.newVersion.localeCompare(pjson.version) === 1) { 594 | log.info('A new version is available: ' + whatsUpp.newVersion) 595 | const options = { 596 | title: pjson.productName, 597 | message: 'A new version is available, download it at https://github.com/alindt/WhatsUpp', 598 | open: 'https://github.com/alindt/WhatsUpp/releases/latest', 599 | sound: true 600 | } 601 | notifier.notify(options, function (err, response) { 602 | if (err) log.warn('Error: ' + err) 603 | }) 604 | } else { 605 | log.info('Already on latest version') 606 | } 607 | } else { 608 | log.warn('Error while checking for updates (status ' + (response !== undefined ? response.statusCode : ' not available') + '): ' + err) 609 | } 610 | }) 611 | }) 612 | 613 | if (config.get('startminimized') !== true) { 614 | whatsUpp.window.show() 615 | } 616 | 617 | whatsUpp.window.on('move', (e, evt) => { 618 | config.set('posX', whatsUpp.window.getBounds().x) 619 | config.set('posY', whatsUpp.window.getBounds().y) 620 | config.set('width', whatsUpp.window.getBounds().width) 621 | config.set('height', whatsUpp.window.getBounds().height) 622 | config.saveConfiguration() 623 | }) 624 | 625 | whatsUpp.window.on('resize', (e, evt) => { 626 | config.set('posX', whatsUpp.window.getBounds().x) 627 | config.set('posY', whatsUpp.window.getBounds().y) 628 | config.set('width', whatsUpp.window.getBounds().width) 629 | config.set('height', whatsUpp.window.getBounds().height) 630 | config.saveConfiguration() 631 | }) 632 | 633 | whatsUpp.window.on('page-title-updated', onlyOSX((event, title) => { 634 | let count = title.match(/\((\d+)\)/) 635 | count = count ? count[1] : '' 636 | app.dock.setBadge(count) 637 | log.info('Badge updated: ' + count) 638 | })) 639 | 640 | whatsUpp.window.on('page-title-updated', onlyLinux((event, title) => { 641 | let count = title.match(/\((\d+)\)/) 642 | count = count ? count[1] : '' 643 | 644 | if (parseInt(count) > 0) { 645 | if (!whatsUpp.window.isFocused() && global.config.get('quietMode') !== true) { 646 | log.info('Flashing frame') 647 | whatsUpp.window.flashFrame(true) 648 | } 649 | const badge = NativeImage.createFromPath(app.getAppPath() + '/assets/badges/badge-' + (count > 9 ? 0 : count) + '.png') 650 | whatsUpp.window.setOverlayIcon(badge, 'new messages') 651 | global.whatsUpp.setNewMessageIcon() 652 | } else { 653 | whatsUpp.window.setOverlayIcon(null, 'no new messages') 654 | global.whatsUpp.clearNewMessageIcon() 655 | } 656 | log.info('Badge updated: ' + count) 657 | })) 658 | 659 | whatsUpp.window.on('page-title-updated', onlyWin((event, title) => { 660 | let count = title.match(/\((\d+)\)/) 661 | count = count ? count[1] : '' 662 | 663 | if (parseInt(count) > 0) { 664 | if (!whatsUpp.window.isFocused()) { 665 | whatsUpp.window.flashFrame(true) 666 | } 667 | const badge = NativeImage.createFromPath(app.getAppPath() + '/assets/badges/badge-' + (count > 9 ? 0 : count) + '.png') 668 | whatsUpp.window.setOverlayIcon(badge, 'new messages') 669 | global.whatsUpp.setNewMessageIcon() 670 | } else { 671 | whatsUpp.window.setOverlayIcon(null, 'no new messages') 672 | global.whatsUpp.clearNewMessageIcon() 673 | } 674 | log.info('Badge updated: ' + count) 675 | })) 676 | 677 | whatsUpp.window.webContents.on('new-window', (e, url) => { 678 | require('electron').shell.openExternal(url) 679 | e.preventDefault() 680 | }) 681 | 682 | whatsUpp.window.on('close', onlyOSX((e) => { 683 | if (whatsUpp.window.forceClose !== true) { 684 | e.preventDefault() 685 | whatsUpp.window.hide() 686 | } 687 | })) 688 | 689 | whatsUpp.window.on('close', onlyWin((e) => { 690 | if (whatsUpp.tray === undefined) { 691 | app.quit() 692 | } else if (whatsUpp.window.forceClose !== true) { 693 | e.preventDefault() 694 | whatsUpp.window.hide() 695 | } 696 | })) 697 | 698 | whatsUpp.window.on('close', onlyLinux((e) => { 699 | if (whatsUpp.tray === undefined) { 700 | app.quit() 701 | } else if (whatsUpp.window.forceClose !== true) { 702 | e.preventDefault() 703 | whatsUpp.window.hide() 704 | } 705 | })) 706 | 707 | whatsUpp.window.on('close', function () { 708 | if (settings.window) { 709 | settings.window.close() 710 | settings.window = null 711 | } 712 | }) 713 | 714 | // Toggle contextmenu content when window is shown 715 | whatsUpp.window.on('show', function () { 716 | if (whatsUpp.tray !== undefined) { 717 | whatsUpp.trayContextMenu.items[0].visible = false 718 | whatsUpp.trayContextMenu.items[1].visible = true 719 | 720 | // Need to re-set the contextmenu for this to work under Linux 721 | // TODO: Only trigger this under Linux 722 | whatsUpp.tray.setContextMenu(whatsUpp.trayContextMenu) 723 | } 724 | }) 725 | 726 | // Toggle contextmenu content when window is hidden 727 | whatsUpp.window.on('hide', function () { 728 | if (whatsUpp.tray !== undefined) { 729 | whatsUpp.trayContextMenu.items[0].visible = true 730 | whatsUpp.trayContextMenu.items[1].visible = false 731 | 732 | // Need to re-set the contextmenu for this to work under Linux 733 | // TODO: Only trigger this under Linux 734 | whatsUpp.tray.setContextMenu(whatsUpp.trayContextMenu) 735 | } 736 | }) 737 | 738 | app.on('before-quit', onlyOSX(() => { 739 | whatsUpp.window.forceClose = true 740 | })) 741 | 742 | app.on('before-quit', onlyLinux(() => { 743 | whatsUpp.window.forceClose = true 744 | })) 745 | 746 | app.on('before-quit', onlyWin(() => { 747 | whatsUpp.window.forceClose = true 748 | })) 749 | 750 | app.on('window-all-closed', onlyWin(() => { 751 | app.quit() 752 | })) 753 | } 754 | } 755 | 756 | global.settings = { 757 | init () { 758 | // if there is already one instance of the window created show that one 759 | if (settings.window) { 760 | settings.window.show() 761 | } else { 762 | settings.openWindow() 763 | settings.createMenu() 764 | } 765 | }, 766 | 767 | createMenu () { 768 | settings.menu = new AppMenu() 769 | settings.menu.append(new MenuItem( 770 | { 771 | label: 'close', 772 | visible: false, 773 | accelerator: 'esc', 774 | click () { settings.window.close() } 775 | }) 776 | ) 777 | settings.menu.append(new MenuItem( 778 | { 779 | label: 'Toggle DevTools', 780 | accelerator: 'Ctrl+Shift+I', 781 | visible: false, 782 | click () { settings.window.toggleDevTools() } 783 | }) 784 | ) 785 | settings.menu.append(new MenuItem( 786 | { 787 | label: 'Reload settings view', 788 | accelerator: 'CmdOrCtrl+r', 789 | visible: false, 790 | click () { settings.window.reload() } 791 | }) 792 | ) 793 | settings.window.setMenu(settings.menu) 794 | settings.window.setMenuBarVisibility(false) 795 | }, 796 | 797 | openWindow () { 798 | settings.window = new BrowserWindow( 799 | { 800 | width: 550, 801 | height: 550, 802 | resizable: true, 803 | center: true, 804 | frame: true, 805 | webPreferences: { 806 | nodeIntegration: true 807 | } 808 | } 809 | ) 810 | 811 | // settings.window.loadURL('file://' + __dirname + '/html/settings.html') 812 | settings.window.loadURL('file://' + join(__dirname, 'html', 'settings.html')) 813 | settings.window.show() 814 | 815 | settings.window.on('close', () => { 816 | settings.window = null 817 | }) 818 | } 819 | } 820 | 821 | global.pjson = pjson 822 | global.about = { 823 | init () { 824 | // if there is already one instance of the window created show that one 825 | if (about.window) { 826 | about.window.show() 827 | } else { 828 | about.openWindow() 829 | about.createMenu() 830 | } 831 | }, 832 | 833 | createMenu () { 834 | about.menu = new AppMenu() 835 | about.menu.append(new MenuItem( 836 | { 837 | label: 'close', 838 | visible: false, 839 | accelerator: 'esc', 840 | click () { about.window.close() } 841 | }) 842 | ) 843 | about.menu.append(new MenuItem( 844 | { 845 | label: 'Toggle DevTools', 846 | accelerator: 'Ctrl+Shift+I', 847 | visible: false, 848 | click () { about.window.toggleDevTools() } 849 | }) 850 | ) 851 | about.menu.append(new MenuItem( 852 | { 853 | label: 'Reload settings view', 854 | accelerator: 'CmdOrCtrl+r', 855 | visible: false, 856 | click () { about.window.reload() } 857 | }) 858 | ) 859 | about.window.setMenu(about.menu) 860 | about.window.setMenuBarVisibility(false) 861 | }, 862 | 863 | openWindow () { 864 | about.window = new BrowserWindow( 865 | { 866 | width: 600, 867 | height: 450, 868 | resizable: true, 869 | center: true, 870 | frame: true, 871 | webPreferences: { 872 | nodeIntegration: true 873 | } 874 | } 875 | ) 876 | 877 | // about.window.loadURL('file://' + __dirname + '/html/about.html') 878 | about.window.loadURL('file://' + join(__dirname, 'html', 'about.html')) 879 | about.window.show() 880 | about.window.webContents.on('new-window', (e, url) => { 881 | require('electron').shell.openExternal(url) 882 | e.preventDefault() 883 | }) 884 | 885 | about.window.on('close', () => { 886 | about.window = null 887 | }) 888 | } 889 | } 890 | 891 | const { ipcMain } = require('electron') 892 | ipcMain.on('phoneinfoupdate', (event, arg) => { 893 | global.phoneinfo.infos = arg 894 | if (arg.info !== 'NORMAL') { 895 | global.whatsUpp.setWarningTray() 896 | } else { 897 | global.whatsUpp.setNormalTray() 898 | } 899 | }) 900 | ipcMain.on('notificationClick', (event, arg) => { 901 | global.whatsUpp.window.show() 902 | global.whatsUpp.window.setAlwaysOnTop(true) 903 | global.whatsUpp.window.focus() 904 | global.whatsUpp.window.setAlwaysOnTop(false) 905 | }) 906 | 907 | global.phoneinfo = { 908 | init () { 909 | // if there is already one instance of the window created show that one 910 | if (phoneinfo.window) { 911 | phoneinfo.window.show() 912 | } else { 913 | phoneinfo.openWindow() 914 | phoneinfo.createMenu() 915 | } 916 | }, 917 | 918 | createMenu () { 919 | phoneinfo.menu = new AppMenu() 920 | phoneinfo.menu.append(new MenuItem( 921 | { 922 | label: 'close', 923 | visible: false, 924 | accelerator: 'esc', 925 | click () { phoneinfo.window.close() } 926 | }) 927 | ) 928 | phoneinfo.menu.append(new MenuItem( 929 | { 930 | label: 'Reload phoneinfo view', 931 | accelerator: 'CmdOrCtrl+r', 932 | visible: false, 933 | click () { phoneinfo.window.reload() } 934 | }) 935 | ) 936 | phoneinfo.menu.append(new MenuItem({ 937 | label: 'Toggle Developer Tools', 938 | accelerator: (function () { 939 | if (process.platform === 'darwin') { return 'Alt+Command+I' } else { return 'Ctrl+Shift+I' } 940 | })(), 941 | click: function (item, focusedWindow) { 942 | if (focusedWindow) { focusedWindow.toggleDevTools() } 943 | } 944 | })) 945 | phoneinfo.window.setMenu(phoneinfo.menu) 946 | phoneinfo.window.setMenuBarVisibility(false) 947 | }, 948 | 949 | openWindow () { 950 | phoneinfo.window = new BrowserWindow( 951 | { 952 | width: 500, 953 | height: 500, 954 | resizable: true, 955 | center: true, 956 | frame: true, 957 | webPreferences: { 958 | nodeIntegration: true 959 | } 960 | } 961 | ) 962 | 963 | // phoneinfo.window.loadURL('file://' + __dirname + '/html/phoneinfo.html') 964 | phoneinfo.window.loadURL('file://' + join(__dirname, 'html', 'phoneinfo.html')) 965 | phoneinfo.window.show() 966 | 967 | phoneinfo.window.on('close', () => { 968 | phoneinfo.window = null 969 | }) 970 | } 971 | } 972 | 973 | app.on('ready', () => { 974 | // Cleanup UA string for "conformity"... 975 | const r = new RegExp(' (' + pjson.name + '|electron)/[^\\s]+', 'gi') 976 | const ua = AppSession.defaultSession.getUserAgent().replace(r, '') 977 | AppSession.defaultSession.setUserAgent(ua) 978 | 979 | if (config.get('useProxy')) { 980 | const proxyType = config.get('proxyType') 981 | const proxyURI = config.get('proxyURI') 982 | const proxy = proxyType + '://' + proxyURI 983 | log.info('Proxy configured: ' + proxy) 984 | AppSession.defaultSession.setProxy({ proxyRules: proxy }, function () {}) 985 | } else { 986 | log.info('No proxy') 987 | } 988 | 989 | whatsUpp.init() 990 | // setting of globalShortcut 991 | if (config.get('globalshortcut') === true) { 992 | globalShortcut.register('CmdOrCtrl + Alt + W', function () { 993 | if (whatsUpp.window.isFocused()) { whatsUpp.window.hide() } else { whatsUpp.window.show() } 994 | }) 995 | } 996 | }) 997 | 998 | // unregistering the globalShorcut on quit of application 999 | app.on('will-quit', function () { 1000 | if (config.get('globalshortcut') === true) { 1001 | globalShortcut.unregisterAll() 1002 | } 1003 | }) 1004 | })(this) 1005 | -------------------------------------------------------------------------------- /app/menu.js: -------------------------------------------------------------------------------- 1 | // vim: set ts=2 sw=2 expandtab: 2 | 3 | /* global _, whatsUpp */ 4 | 5 | (function (scope) { 6 | 'use strict' 7 | 8 | const template = [ 9 | { 10 | label: '&' + _('Edit'), 11 | submenu: [ 12 | { 13 | label: _('Undo'), 14 | accelerator: 'CmdOrCtrl+Z', 15 | role: 'undo' 16 | }, 17 | { 18 | label: _('Redo'), 19 | accelerator: 'Shift+CmdOrCtrl+Z', 20 | role: 'redo' 21 | }, 22 | { 23 | type: 'separator' 24 | }, 25 | { 26 | label: _('Cut'), 27 | accelerator: 'CmdOrCtrl+X', 28 | role: 'cut' 29 | }, 30 | { 31 | label: _('Copy'), 32 | accelerator: 'CmdOrCtrl+C', 33 | role: 'copy' 34 | }, 35 | { 36 | label: _('Paste'), 37 | accelerator: 'CmdOrCtrl+V', 38 | role: 'paste' 39 | }, 40 | { 41 | label: _('Select All'), 42 | accelerator: 'CmdOrCtrl+A', 43 | role: 'selectall' 44 | }, 45 | { 46 | type: 'separator' 47 | }, 48 | { 49 | label: _('Settings'), 50 | accelerator: 'CmdOrCtrl+,', 51 | click: function () { 52 | global.settings.init() 53 | } 54 | } 55 | ] 56 | }, 57 | { 58 | label: '&' + _('View'), 59 | submenu: [ 60 | { 61 | label: _('Reload'), 62 | accelerator: 'CmdOrCtrl+R', 63 | click: function (item, focusedWindow) { 64 | if (focusedWindow) { 65 | // Remove ServiceWorker to allow reloading 66 | whatsUpp.window.webContents.unregisterServiceWorker(function () { return true }) 67 | 68 | focusedWindow.reload() 69 | } 70 | } 71 | }, 72 | { type: 'separator' }, 73 | { 74 | label: _('Toggle Full Screen'), 75 | accelerator: (function () { 76 | if (process.platform === 'darwin') { return 'Ctrl+Command+F' } else { return 'F11' } 77 | })(), 78 | click: function (item, focusedWindow) { 79 | if (focusedWindow) { focusedWindow.setFullScreen(!focusedWindow.isFullScreen()) } 80 | } 81 | }, 82 | { 83 | label: _('Dark mode'), 84 | accelerator: 'CmdOrCtrl+Shift+Alt+D', 85 | type: 'checkbox', 86 | checked: (function () { 87 | return global.config.get('darkMode') 88 | })(), 89 | click: function (item, focusedWindow) { 90 | global.config.set('darkMode', global.config.get('darkMode') !== true) 91 | item.checked = global.config.get('darkMode') 92 | global.config.saveConfiguration() 93 | global.config.applyConfiguration() 94 | if (focusedWindow) { focusedWindow.reload() } 95 | } 96 | }, 97 | { 98 | label: _('Quiet mode'), 99 | accelerator: 'CmdOrCtrl+Shift+Alt+Q', 100 | type: 'checkbox', 101 | checked: (function () { 102 | return global.config.get('quietMode') 103 | })(), 104 | click: function (item, focusedWindow) { 105 | global.config.set('quietMode', global.config.get('quietMode') !== true) 106 | item.checked = global.config.get('quietMode') 107 | global.config.saveConfiguration() 108 | } 109 | }, 110 | { type: 'separator' }, 111 | { 112 | label: _('Toggle Developer Tools'), 113 | accelerator: (function () { 114 | if (process.platform === 'darwin') { return 'Alt+Command+I' } else { return 'Ctrl+Shift+I' } 115 | })(), 116 | click: function (item, focusedWindow) { 117 | if (focusedWindow) { focusedWindow.toggleDevTools() } 118 | } 119 | }, 120 | { type: 'separator' }, 121 | { 122 | label: _('Phone info'), 123 | accelerator: (function () { 124 | if (process.platform === 'darwin') { return 'Alt+Command+N' } else { return 'Ctrl+Shift+N' } 125 | })(), 126 | click: function (item, focusedWindow) { 127 | if (focusedWindow) { global.phoneinfo.init() } 128 | } 129 | } 130 | ] 131 | }, 132 | { 133 | label: '&' + _('Window'), 134 | role: 'window', 135 | submenu: [ 136 | { 137 | label: _('Minimize'), 138 | accelerator: 'CmdOrCtrl+M', 139 | role: 'minimize' 140 | }, 141 | { 142 | label: _('Close'), 143 | accelerator: 'CmdOrCtrl+W', 144 | role: 'close' 145 | } 146 | ] 147 | }, 148 | { 149 | label: '&' + _('Audio'), 150 | submenu: [ 151 | { 152 | label: _('Increase Audio Rate by 20%'), 153 | accelerator: 'CmdOrCtrl+=', 154 | click: function (item, focusedWindow) { 155 | focusedWindow && focusedWindow.webContents.executeJavaScript( 156 | 'window.audioRate = (window.audioRate || 1) + 0.2' 157 | ) 158 | } 159 | }, 160 | { 161 | label: _('Decrease Audio Rate by 20%'), 162 | accelerator: 'CmdOrCtrl+-', 163 | click: function (item, focusedWindow) { 164 | focusedWindow && focusedWindow.webContents.executeJavaScript( 165 | 'window.audioRate = (window.audioRate || 1) - 0.2' 166 | ) 167 | } 168 | } 169 | ] 170 | } 171 | ] 172 | 173 | if (process.platform === 'darwin') { 174 | const name = 'WhatsUpp' 175 | template.unshift({ 176 | label: '&' + name, 177 | submenu: [ 178 | { 179 | label: _('About') + ' ' + name, 180 | role: 'about' 181 | }, 182 | { 183 | type: 'separator' 184 | }, 185 | { 186 | label: _('Hide') + ' ' + name, 187 | accelerator: 'Command+H', 188 | role: 'hide' 189 | }, 190 | { 191 | label: _('Hide Others'), 192 | accelerator: 'Command+Alt+H', 193 | role: 'hideothers' 194 | }, 195 | { 196 | label: _('Show All'), 197 | role: 'unhide' 198 | }, 199 | { 200 | type: 'separator' 201 | }, 202 | { 203 | label: _('Quit'), 204 | accelerator: 'Command+Q', 205 | click: () => { require('electron').app.quit() } 206 | } 207 | ] 208 | }) 209 | // Window menu. 210 | template[3].submenu.push( 211 | { 212 | type: 'separator' 213 | }, 214 | { 215 | label: _('Bring All to Front'), 216 | role: 'front' 217 | } 218 | ) 219 | } else if (process.platform === 'linux' || process.platform === 'win64' || process.platform === 'win32') { 220 | template.unshift({ 221 | label: '&File', 222 | submenu: [ 223 | { 224 | label: _('About'), 225 | click: () => { global.about.init() } 226 | }, 227 | { 228 | label: _('Quit'), 229 | accelerator: 'Ctrl+Q', 230 | click: () => { require('electron').app.quit() } 231 | } 232 | ] 233 | }) 234 | } 235 | 236 | module.exports = template 237 | })(this) 238 | -------------------------------------------------------------------------------- /app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | " vim: set ts=2 sw=2 expandtab:": "vim modeline, not part of data", 3 | "name": "whatsupp", 4 | "productName": "WhatsUpp", 5 | "version": "0.8.0", 6 | "revision": "1", 7 | "reltype": "stable", 8 | "releases": "https://api.github.com/repos/alindt/WhatsUpp/releases", 9 | "license": "GPL-3.0", 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/alindt/WhatsUpp.git" 13 | }, 14 | "main": "main.js", 15 | "author": "alindt ", 16 | "maintainer": "alindt ", 17 | "description": "Native desktop app/wrapper for https://web.whatsapp.com. Built with Electron.", 18 | "dependencies": { 19 | "auto-launch": "^5.0.5", 20 | "electron": "19.0.8", 21 | "electron-context-menu": "^0.12.0", 22 | "electron-log": "^3.0.5", 23 | "find": "^0.3.0", 24 | "fs-extra": "^7.0.1", 25 | "gettext-parser": "^4.0.0", 26 | "jquery": "3.4.0", 27 | "materialize-css": "1.0.0", 28 | "node-gettext": "^2.0.0", 29 | "node-notifier": "^5.4.0", 30 | "request": "^2.88.0", 31 | "got":"^12.1.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /assets/icons/whatsupp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alindt/WhatsUpp/ad23e969bd0318154e4ab73210096b5fbf0cd500/assets/icons/whatsupp.png -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | whatsapp-desktop (0.5.1-1) unstable; urgency=low 2 | 3 | * Fix 'Chrome 36' error 4 | 5 | -- Alin Sat, 31 Mar 2018 11:25:47 +0200 6 | 7 | whatsapp-desktop (0.5.0-1) unstable; urgency=low 8 | 9 | * Bugfix 10 | * Dark mode 11 | 12 | -- Enrico Sat, 31 Mar 2018 11:25:47 +0200 13 | 14 | whatsapp-desktop (0.4.2-1) unstable; urgency=low 15 | 16 | * Fixed build issue 17 | 18 | -- Enrico Wed, 03 Jan 2018 16:33:00 +0200 19 | 20 | whatsapp-desktop (0.4.1-1) unstable; urgency=low 21 | 22 | * Added flatpak/AppImage support 23 | * Added feature: open main window on notification click 24 | * Bugfix: fixed various bugs on macOS 25 | 26 | -- Enrico Tue, 02 Jan 2018 22:08:05 +0200 27 | 28 | whatsapp-desktop (0.4.0-1) unstable; urgency=low 29 | 30 | * Bugfix 31 | * German translations (thanks to @wotomg) 32 | 33 | -- Enrico Sun, 31 Dec 2017 00:04:30 +0200 34 | 35 | whatsapp-desktop (0.3.14-1) unstable; urgency=low 36 | 37 | * Various bugfixes, update notifications 38 | 39 | -- Enrico Sat, 04 Nov 2017 18:30:00 +0200 40 | 41 | whatsapp-desktop (0.3.13-1) unstable; urgency=low 42 | 43 | * Fixed some bugs 44 | * Added a red-dot over tray icons on new messages (thanks to @Termuellinator) 45 | * Added Spanish locale (thanks to @mlopezcoria) 46 | * Added Portuguese Brazil locale (thanks to @Dssdiego) 47 | 48 | -- Enrico Mon, 28 Aug 2017 20:29:02 +0200 49 | 50 | whatsapp-desktop (0.3.12-1) unstable; urgency=medium 51 | 52 | * Added ability to inject custom CSS 53 | * Bugfix 54 | 55 | -- Enrico Tue, 1 Aug 2017 00:00:00 +0200 56 | 57 | whatsapp-desktop (0.3.11-1) unstable; urgency=medium 58 | 59 | * Added logging system with CLI option 60 | * Added auto-launch at login option 61 | * Hide tray icon (#5) 62 | * fixed tray icon click doesn't fire (#6) 63 | * Fixed missing dependency 64 | * Skip setting saving if object is invalid (see #8) 65 | * Other bugfixes 66 | 67 | -- Enrico Wed, 19 Jul 2017 12:46:00 +0200 68 | 69 | whatsapp-desktop (0.3.6-1) unstable; urgency=medium 70 | 71 | * NativeImage electron class renamed to nativeImage 72 | 73 | -- Enrico Tue, 27 Jun 2017 21:58:04 +0200 74 | 75 | whatsapp-desktop (0.3.5-1) unstable; urgency=medium 76 | 77 | * Initial Release. 78 | 79 | -- Enrico Wed, 21 Jun 2017 22:39:32 +0200 80 | 81 | whatsapp-desktop (0.3.4-1) unstable; urgency=low 82 | 83 | * Initial Release. 84 | 85 | -- Enrico Wed, 21 Jun 2017 20:27:16 +0200 86 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: whatsupp 2 | Section: net 3 | Priority: optional 4 | Maintainer: alindt 5 | Build-Depends: debhelper (>= 9) 6 | Standards-Version: 3.9.5 7 | Homepage: https://github.com/alindt/WhatsUpp 8 | Vcs-Git: https://github.com/alindt/WhatsUpp.git 9 | 10 | Package: whatsupp 11 | Architecture: amd64 armhf 12 | Depends: ${shlibs:Depends}, ${misc:Depends}, libnotify4, gconf2, libgconf-2-4 13 | Description: Native desktop app/wrapper for https://web.whatsapp.com. Built with Electron. 14 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: whatsupp 3 | Source: 4 | 5 | Files: * 6 | Copyright: 7 | 8 | License: GPL-3.0+ 9 | 10 | Files: debian/* 11 | Copyright: 2019 alindt 12 | License: GPL-3.0+ 13 | 14 | License: GPL-3.0+ 15 | This program is free software: you can redistribute it and/or modify 16 | it under the terms of the GNU General Public License as published by 17 | the Free Software Foundation, either version 3 of the License, or 18 | (at your option) any later version. 19 | . 20 | This package is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | . 25 | You should have received a copy of the GNU General Public License 26 | along with this program. If not, see . 27 | . 28 | On Debian systems, the complete text of the GNU General 29 | Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". 30 | 31 | # Please also look if there are files or directories which have a 32 | # different copyright/license attached and list them here. 33 | # Please avoid to pick license terms that are more restrictive than the 34 | # packaged work, as it may make Debian's contributions unacceptable upstream. 35 | -------------------------------------------------------------------------------- /debian/docs: -------------------------------------------------------------------------------- 1 | readme.md 2 | -------------------------------------------------------------------------------- /debian/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # postinst script 3 | # 4 | # see: dh_installdeb(1) 5 | 6 | set -e 7 | 8 | # summary of how this script can be called: 9 | # * `configure' 10 | # * `abort-upgrade' 11 | # * `abort-remove' `in-favour' 12 | # 13 | # * `abort-remove' 14 | # * `abort-deconfigure' `in-favour' 15 | # `removing' 16 | # 17 | # for details, see http://www.debian.org/doc/debian-policy/ or 18 | # the debian-policy package 19 | 20 | case "$1" in 21 | 22 | configure) 23 | ln -s /opt/whatsupp/WhatsUpp /usr/local/bin/WhatsUpp 24 | ;; 25 | 26 | abort-upgrade|abort-remove|abort-deconfigure) 27 | rm -f /usr/local/bin/WhatsUpp 28 | exit 0 29 | ;; 30 | 31 | *) 32 | echo "postinst called with unknown argument \`$1'" >&2 33 | exit 1 34 | ;; 35 | 36 | esac 37 | 38 | # dh_installdeb will replace this with shell code automatically 39 | # generated by other debhelper scripts. 40 | 41 | #DEBHELPER# 42 | 43 | exit 0 44 | -------------------------------------------------------------------------------- /debian/prerm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # prerm script 3 | # 4 | # see: dh_installdeb(1) 5 | 6 | set -e 7 | 8 | # summary of how this script can be called: 9 | # * `remove' 10 | # * `upgrade' 11 | # * `failed-upgrade' 12 | # * `remove' `in-favour' 13 | # * `deconfigure' `in-favour' 14 | # `removing' 15 | # 16 | # for details, see http://www.debian.org/doc/debian-policy/ or 17 | # the debian-policy package 18 | 19 | case "$1" in 20 | remove|upgrade|deconfigure) 21 | rm -f /usr/local/bin/WhatsUpp 22 | ;; 23 | 24 | failed-upgrade) 25 | ;; 26 | 27 | *) 28 | echo "prerm called with unknown argument \`$1'" >&2 29 | exit 1 30 | ;; 31 | esac 32 | 33 | # dh_installdeb will replace this with shell code automatically 34 | # generated by other debhelper scripts. 35 | 36 | #DEBHELPER# 37 | 38 | exit 0 39 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # See debhelper(7) (uncomment to enable) 3 | # output every command that modifies files on the build system. 4 | #DH_VERBOSE = 1 5 | 6 | # see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/* 7 | DPKG_EXPORT_BUILDFLAGS = 1 8 | include /usr/share/dpkg/default.mk 9 | 10 | # see FEATURE AREAS in dpkg-buildflags(1) 11 | #export DEB_BUILD_MAINT_OPTIONS = hardening=+all 12 | 13 | # see ENVIRONMENT in dpkg-buildflags(1) 14 | # package maintainers to append CFLAGS 15 | #export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic 16 | # package maintainers to append LDFLAGS 17 | #export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed 18 | 19 | 20 | # main packaging script based on dh7 syntax 21 | %: 22 | dh $@ 23 | 24 | binary-arch: 25 | mkdir -p debian/whatsupp/opt/whatsupp/ 26 | mkdir -p debian/whatsupp/usr/share/applications/ 27 | mkdir -p debian/whatsupp/usr/share/metainfo/ 28 | mkdir -p debian/whatsupp/usr/share/icons/hicolor/128x128/apps/ 29 | mkdir -p debian/whatsupp/usr/share/icons/hicolor/64x64/apps/ 30 | cp "app/assets/icon/icon@2x.png" debian/whatsupp/usr/share/icons/hicolor/128x128/apps/whatsupp.png 31 | cp "app/assets/icon/icon.png" debian/whatsupp/usr/share/icons/hicolor/64x64/apps/whatsupp.png 32 | cp whatsupp.desktop debian/whatsupp/usr/share/applications/ 33 | cp eu.alindt.whatsupp.appdata.xml debian/whatsupp/usr/share/metainfo/ 34 | ifeq ($(DEB_HOST_ARCH),) 35 | echo "Target architecture not specified" 36 | exit 1 37 | endif 38 | 39 | ifeq ($(DEB_HOST_ARCH),armhf) 40 | cp -r dist/WhatsUpp-linux-armv7l/* debian/whatsupp/opt/whatsupp/ 41 | endif 42 | ifeq ($(DEB_HOST_ARCH),amd64) 43 | cp -r dist/WhatsUpp-linux-x64/* debian/whatsupp/opt/whatsupp/ 44 | endif 45 | 46 | # debmake generated override targets 47 | # This is example for Cmake (See http://bugs.debian.org/641051 ) 48 | #override_dh_auto_configure: 49 | # dh_auto_configure -- \ 50 | # -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH) 51 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (native) 2 | -------------------------------------------------------------------------------- /eu.alindt.whatsupp.appdata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | eu.alindt.whatsupp.desktop 4 | CC0-1.0 5 | GPL-3.0+ 6 | WhatsUpp 7 | Electron client for The-IM-Service-That-Shall-Not-Be-Named™ 8 | 9 |

10 | Native client/wrapper for https://web.whatsapp.com 11 |

12 |
13 | 14 | https://camo.githubusercontent.com/25f207f8cfa91ad13a0fe303bc6fa0d0265719d6/687474703a2f2f69312d77696e2e736f667470656469612d7374617469632e636f6d2f73637265656e73686f74732f57686174734170702d4465736b746f705f312e706e67 15 | 16 | https://github.com/alindt/WhatsUpp 17 | https://github.com/alindt/WhatsUpp/issues 18 | whatsupp_at_cevreau_dot_eu 19 | inkscape 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | " vim: set ts=2 sw=2 expandtab:": "vim modeline, not part of data", 3 | "name": "whatsupp", 4 | "productName": "WhatsUpp", 5 | "version": "0.8.0", 6 | "revision": "1", 7 | "reltype": "stable", 8 | "repository": "https://github.com/alindt/WhatsUpp.git", 9 | "releases": "https://api.github.com/repos/alindt/WhatsUpp/releases", 10 | "description": "Native desktop app/wrapper for https://web.whatsapp.com. Built with Electron.", 11 | "main": "app/main.js", 12 | "scripts": { 13 | "dev": "standard -v && electron --debug=5858 ./app", 14 | "preinstall": "cd app && yarn", 15 | "gettext": "xgettext app/*.js -j --omit-header -o app/locale/messages.pot && xgettext app/html/*.html -L JavaScript -j --omit-header -o app/locale/messages.pot", 16 | "test": "standard -v", 17 | "clean": "rm -rf dist node_modules app/node_modules yarn.lock app/yarn.lock", 18 | "build:linux64": "standard -v && electron-packager ./app \"WhatsUpp\" --out=dist --overwrite --package-manager=yarn --platform=linux --arch=x64 --asar --electron-version=19.0.8 --icon=assets/icons/whatsupp.png", 19 | "build-dev:linux64": "standard -v && electron-packager ./app \"WhatsUpp-dev\" --out=dist --overwrite --package-manager=yarn --platform=linux --arch=x64 --asar --electron-version=19.0.8 --icon=assets/icons/whatsupp.png", 20 | "build": "yarn build:linux64", 21 | "build-dev": "yarn build-dev:linux64", 22 | "pkg:debian64": "electron-installer-debian --bin WhatsUpp --src dist/WhatsUpp-linux-x64/ --dest dist/pkg --arch amd64 --section net --icon assets/icons/whatsupp.png", 23 | "pkg:debian": "yarn pkg:debian64", 24 | "pkg-dev:debian64": "electron-installer-debian --bin WhatsUpp-dev --src dist/WhatsUpp-dev-linux-x64/ --dest dist/pkg --arch amd64 --section net --icon assets/icons/whatsupp.png", 25 | "pkg-dev:debian": "yarn pkg-dev:debian64", 26 | "pkg": "yarn pkg:debian", 27 | "pkg-dev": "yarn pkg-dev:debian" 28 | }, 29 | "devDependencies": { 30 | "electron": "^19.0.8", 31 | "electron-installer-debian": "^3.1.0", 32 | "electron-packager": "^15.5.1", 33 | "fs-extra": "^10.1.0", 34 | "standard": "^17.0.0" 35 | }, 36 | "dependencies": { 37 | "electron-compile": "^6.4.4", 38 | "find": "^0.3.0", 39 | "got": "^12.1.0", 40 | "jquery": "3.6.0", 41 | "materialize-css": "1.0.0", 42 | "process-nextick-args": "^2.0.0", 43 | "util-deprecate": "^1.0.2", 44 | "yarn": "^1.22.19" 45 | }, 46 | "build": { 47 | "appId": "eu.alindt.whatsupp", 48 | "linux": { 49 | "category": "Utility", 50 | "icon": "assets/icons/" 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packager.json: -------------------------------------------------------------------------------- 1 | { 2 | " vim: set ts=2 sw=2 expandtab:": "vim modeline, not part of data", 3 | "osx": { 4 | "title": "WhatsUpp", 5 | "icon": "assets/osx/whatsupp.icns", 6 | "icon-size": 80, 7 | "contents": [ 8 | { 9 | "x": 438, 10 | "y": 344, 11 | "type": "link", 12 | "path": "/Applications" 13 | }, 14 | { 15 | "x": 192, 16 | "y": 344, 17 | "type": "file" 18 | } 19 | ] 20 | }, 21 | "win": { 22 | "title": "WhatsUpp", 23 | "icon": "assets/win/whatsupp.ico", 24 | "icon-size": 48, 25 | "app-bundle-id": "WhatsUpp" 26 | }, 27 | "linux": { 28 | "title": "WhatsUpp", 29 | "icon": "assets/win/whatsupp.ico", 30 | "icon-size": 48, 31 | "app-bundle-id": "WhatsUpp" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # WhatsUpp [![CircleCI](https://circleci.com/gh/alindt/WhatsUpp/tree/master.svg?style=shield&circle-token=ee4ce35cba209e8d63e4df51ae5545468820e0ef)](https://circleci.com/gh/alindt/WhatsUpp/tree/master) [![CodeFactor](https://www.codefactor.io/repository/github/alindt/whatsupp/badge/master)](https://www.codefactor.io/repository/github/alindt/whatsupp/overview/master) [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com) ![libraries.io](https://img.shields.io/librariesio/github/alindt/WhatsUpp.svg) 2 | 3 | Linux native desktop app/wrapper for https://web.whatsapp.com. Built with [Electron](https://electronjs.org/). 4 | This project continues the work of [@Enrico204](https://github.com/Enrico204/Whatsapp-Desktop) and [@bcalik](https://github.com/bcalik/Whatsapp-Desktop) 5 | 6 | ## Features 7 | 8 | * ![OK](https://img.shields.io/badge/-OK-green.svg) Linux only (~ia32~/amd64) 9 | * ![OK](https://img.shields.io/badge/-OK-green.svg) Native notifications 10 | * ![OK](https://img.shields.io/badge/-OK-green.svg) System tray icon 11 | * ![OK](https://img.shields.io/badge/-OK-green.svg) Open links in default browser 12 | * ![TEST](https://img.shields.io/badge/-TEST-blue.svg) Badge with the number of notifications in the tray/dock/taskbar ([#3](https://github.com/alindt/WhatsUpp/issues/3)) 13 | * ![OK](https://img.shields.io/badge/-OK-green.svg) Focus on search bar with CTRL+F 14 | * ![FIX](https://img.shields.io/badge/-FIX-red.svg) Phone info window (s/w versions, battery status, etc) ([#4](https://github.com/alindt/WhatsUpp/issues/4)) 15 | * ![TEST](https://img.shields.io/badge/-TEST-blue.svg) Auto-launch on login ([#5](https://github.com/alindt/WhatsUpp/issues/5)) 16 | * ![OK](https://img.shields.io/badge/-OK-green.svg) Start minimized to tray icon 17 | * ![OK](https://img.shields.io/badge/-OK-green.svg) Logging system (log to console and `$HOME/.config/WhatsUpp/log.log`) 18 | * ![FIX](https://img.shields.io/badge/-FIX-red.svg) Apply custom CSS stylesheet ([#6](https://github.com/alindt/WhatsUpp/issues/6)) 19 | * ![OK](https://img.shields.io/badge/-OK-green.svg) Auto-hide menu bar 20 | * ![OK](https://img.shields.io/badge/-OK-green.svg) Disabling GPU rendering (useful when dealing with bugged video drivers) 21 | * A couple of things can be configured: 22 | * ![OK](https://img.shields.io/badge/-OK-green.svg) Toggle avatar visibility 23 | * ![OK](https://img.shields.io/badge/-OK-green.svg) Toggle preview of the messages visibility 24 | * ![TEST](https://img.shields.io/badge/-TEST-blue.svg) Set the size for the media thumbs ([#10](https://github.com/alindt/WhatsUpp/issues/10)) 25 | * ![OK](https://img.shields.io/badge/-OK-green.svg) Proxy settings for connection 26 | 27 | ## Command line switches 28 | 29 | --debug-log Switch file's log level to "debug" (default: "warn") 30 | 31 | ## Contributions 32 | 33 | Contributions are welcome! For feature requests and bug reports please submit an [issue](https://github.com/alindt/WhatsUpp/issues). 34 | 35 | ## Build from source 36 | 37 | ``` 38 | git clone https://github.com/alindt/WhatsUpp 39 | cd WhatsUpp 40 | yarn install 41 | yarn build:$platform 42 | ``` 43 | 44 | `$platform` can be one of `linux32`, `linux64` or `linux` (builds both). 45 | 46 | You'll find artifacts in the `./dist/` directory. 47 | 48 | ## Run on-the-fly (for devs) 49 | 50 | Run `yarn dev` (in project root) instead of compiling the code each time. 51 | -------------------------------------------------------------------------------- /whatsupp.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Version=1.0 4 | Name=WhatsUpp 5 | Comment=WhatsUpp unofficial client 6 | Exec=/opt/whatsupp/WhatsUpp 7 | StartupNotify=false 8 | Terminal=false 9 | Categories=Network;InstantMessaging; 10 | Icon=whatsupp 11 | StartupWMClass=whatsupp 12 | -------------------------------------------------------------------------------- /whatsupp.spec: -------------------------------------------------------------------------------- 1 | 2 | %define __spec_install_post %{nil} 3 | %define debug_package %{nil} 4 | %define __os_install_post %{_dbpath}/brp-compress 5 | 6 | Summary: WhatsUpp 7 | Name: WhatsUpp 8 | Version: 0.6.1 9 | Release: 1 10 | License: GPL 11 | Group: None 12 | Packager: alindt 13 | BuildArchitectures: x86_64 14 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root 15 | Source: dummy.tar.bz2 16 | Requires: libXScrnSaver 17 | Provides: libffmpeg.so()(64bit) 18 | 19 | %description 20 | Native desktop app/wrapper for https://web.whatsapp.com. Built with Electron. 21 | 22 | %prep 23 | %setup -c -q -T -D -a 0 24 | 25 | %build 26 | # Empty section. 27 | 28 | %install 29 | rm -rf %{buildroot} 30 | mkdir -p %{buildroot} 31 | mkdir -p %{buildroot}/usr/share/applications/ 32 | mkdir -p %{buildroot}/usr/share/metainfo/ 33 | mkdir -p %{buildroot}/usr/share/icons/hicolor/128x128/apps/ 34 | mkdir -p %{buildroot}/usr/share/icons/hicolor/64x64/apps/ 35 | cp "%{_topdir}/../app/assets/icon/icon@2x.png" %{buildroot}/usr/share/icons/hicolor/128x128/apps/whatsupp.png 36 | cp "%{_topdir}/../app/assets/icon/icon.png" %{buildroot}/usr/share/icons/hicolor/64x64/apps/whatsupp.png 37 | cp %{_topdir}/../whatsupp.desktop %{buildroot}/usr/share/applications/ 38 | cp %{_topdir}/../eu.alindt.whatsupp.appdata.xml %{buildroot}/usr/share/metainfo/ 39 | # copy files in builddir 40 | install -d -m 0755 %{buildroot}/opt/whatsupp/ 41 | install -d -m 0755 %{buildroot}/%{_bindir} 42 | cp -ar %{_topdir}/../dist/WhatsUpp-linux-x64/* %{buildroot}/opt/whatsupp/ 43 | ln -sf /opt/whatsupp/WhatsUpp %{buildroot}/%{_bindir}/WhatsUpp 44 | 45 | %clean 46 | rm -rf %{buildroot} 47 | 48 | 49 | %files 50 | %defattr(-,root,root,-) 51 | /opt/whatsupp/* 52 | %{_bindir}/WhatsUpp 53 | /usr/share/applications/whatsupp.desktop 54 | /usr/share/metainfo/eu.alindt.whatsupp.appdata.xml 55 | /usr/share/icons/hicolor/128x128/apps/whatsupp.png 56 | /usr/share/icons/hicolor/64x64/apps/whatsupp.png 57 | 58 | %changelog 59 | * Sun Apr 29 2018 alindt 0.6.1-1 60 | - See debian changelog in repo 61 | 62 | * Sun Apr 22 2018 alindt 0.6.0-1 63 | - See debian changelog in repo 64 | 65 | * Sun Apr 21 2018 alindt 0.5.1-1 66 | - See debian changelog in repo 67 | 68 | * Sat Mar 31 2018 Enrico204 0.5.0-1 69 | - See debian changelog in repo 70 | 71 | * Wed Jan 03 2018 Enrico204 0.4.2-1 72 | - See debian changelog on repo 73 | 74 | * Tue Jan 02 2018 Enrico204 0.4.1-1 75 | - See debian changelog on repo 76 | 77 | * Sun Dec 31 2017 Enrico204 0.4.0-1 78 | - See debian changelog on repo 79 | 80 | * Sat Nov 04 2017 Enrico204 0.3.14-1 81 | - See debian changelog on repo 82 | 83 | * Mon Aug 28 2017 Enrico204 0.3.13-1 84 | - See debian changelog on repo 85 | 86 | * Thu Aug 3 2017 Enrico204 0.3.12-1 87 | - First Build 88 | --------------------------------------------------------------------------------