Compare commits

..
1 Commits
Author SHA1 Message Date
dev c7948236eb Initial commit 2026-10-18 12:19:40 +08:00
567 changed files with 137 additions and 215931 deletions
-4
View File
@@ -1,4 +0,0 @@
{
"presets": ["@babel/preset-react", "@babel/preset-env"],
"comments": false
}
-4
View File
@@ -1,4 +0,0 @@
umd/* binary
package-lock.json binary
*.min.css binary
src/i18n.min/* binary
-39
View File
@@ -1,39 +0,0 @@
name: Deploy im-webapp (k3s test cluster)
on:
workflow_dispatch:
inputs:
image_tag:
description: '镜像tag,默认为 test(与集群 kustomization 里的 newTag 一致)'
required: false
jobs:
deploy:
runs-on: deploy-host
steps:
- uses: actions/checkout@v4
- name: 确定镜像tag
id: vars
run: |
TAG="${{ github.event.inputs.image_tag }}"
[ -z "$TAG" ] && TAG=test
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
- name: 登录镜像仓库
run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login git.118im.com -u admin --password-stdin
- name: 构建并推送镜像
run: |
docker build \
--build-arg TINODE_API_KEY="${{ secrets.TINODE_API_KEY }}" \
-t git.118im.com/im_team/im-webapp:${{ steps.vars.outputs.tag }} .
docker push git.118im.com/im_team/im-webapp:${{ steps.vars.outputs.tag }}
- name: 部署到k3s测试集群
run: |
mkdir -p ~/.kube
echo "${{ secrets.KUBECONFIG }}" > ~/.kube/config
chmod 600 ~/.kube/config
kubectl rollout restart deployment/im-webapp -n im-webapp-system
kubectl rollout status deployment/im-webapp -n im-webapp-system --timeout=120s
-38
View File
@@ -1,38 +0,0 @@
---
name: Bug report
about: Create a report to help us improve TinodeWeb
title: ''
labels: bug
assignees: ''
---
If you want to ask a question, please post to https://groups.google.com/d/forum/tinode instead.
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Environment (please complete the following information):**
- OS: [e.g. Mac OS, Windows 10 Home]
- Browser [e.g. Chrome, Safari]
- TinodeWeb Version [e.g. 0.16.6]
**Console log**
Please attach or insert console log which illustrates the problem. Please use the log produced by `index-dev.html`, not `index.html`; `index.html` uses minified javascript which produces unusable logs.
**Additional context**
Add any other context about the problem here.
-23
View File
@@ -1,23 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: feature request
assignees: ''
---
If you want to ask a question, please post to https://groups.google.com/d/forum/tinode instead.
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+136 -6
View File
@@ -1,8 +1,138 @@
.DS_Store
node_modules
src/i18n/srci/
webapp.code-workspace.code-workspace
# ---> Node
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Local developer overrides — never commit real keys.
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
.claude/
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# vitepress build output
**/.vitepress/dist
# vitepress cache directory
**/.vitepress/cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
-38
View File
@@ -1,38 +0,0 @@
# ---- Stage 1: build static assets ----
# The frontend was fully rewritten from scratch under web/ (Vite + React + TS) on branch
# redesign/desktop-multicolumn, merged into dev 2026-09-09 -- this replaces the old webpack build
# that used to live at the repo root (umd/, css/base.min.css, index.html, etc.). See web/README-
# equivalent context in the redesign plan for why: this Dockerfile previously never touched web/ at
# all, so every "deploy" kept shipping the old app regardless of what was on dev.
FROM node:22-alpine AS build
WORKDIR /app/web
COPY web/package.json web/package-lock.json ./
RUN npm ci
COPY web/. .
# VITE_TINODE_API_KEY is read by src/lib/config.ts (import.meta.env.VITE_TINODE_API_KEY) at build
# time -- Vite only exposes env vars prefixed VITE_ to client code, so the ARG is renamed on its
# way into the build's environment rather than passed through under its old webpack-era name.
ARG TINODE_API_KEY=
ENV VITE_TINODE_API_KEY=$TINODE_API_KEY
RUN npm run build
# ---- Stage 2: serve with nginx ----
FROM nginx:alpine
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
WORKDIR /usr/share/nginx/html
# Vite's build output is fully self-contained: index.html + favicon.svg/icons.svg (from web/public/,
# copied verbatim) + assets/ (content-hashed JS/CSS chunks) -- no separate umd/css/img/audio/
# manifest/service-worker/firebase files the way the old build had, none of that machinery exists
# in the new app.
COPY --from=build /app/web/dist/. ./
HEALTHCHECK --interval=1m --timeout=3s --start-period=10s \
CMD wget -q -O /dev/null http://localhost/ || exit 1
EXPOSE 80
-201
View File
@@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+1 -88
View File
@@ -1,89 +1,2 @@
# Tinode Web
# im_webapp
## Briefing
Single-page web chat application for [Tinode](https://github.com/tinode/chat/). The app is built on
[React](https://reactjs.org/). The [Tinode javascript SDK](https://github.com/tinode/tinode-js/) has no external dependencies.
Overall, it's a lot like open source WhatsApp or Telegram web apps.
Although the app is generally usable, keep in mind that this is work in progress. Some bugs probably exist, some features are missing. The app was tested in the latest Chrome & Firefox only. NPM package is [available](https://www.npmjs.com/package/tinode-webapp).
Try possibly newer or older version live at https://sandbox.tinode.co/.
<a href="https://web.tinode.co/"><img src="web-app.svg" height=36></a>
For demo access and other instructions [see here](https://github.com/tinode/chat/#demosandbox).
## Installing and running
This is _NOT_ a standalone app, this is just a frontend, a client. It requires a [backend](https://github.com/tinode/chat/). See [installation instructions](https://github.com/tinode/chat/blob/master/INSTALL.md). See instructions for [enabling push notifications](push.md).
## Getting support
* Read [client-side](http://tinode.github.io/js-api/) and [server-side](https://github.com/tinode/chat/blob/master/docs/API.md) API documentation.
* For support, general questions, discussions post to [https://groups.google.com/d/forum/tinode](https://groups.google.com/d/forum/tinode).
* For bugs and feature requests [open an issue](https://github.com/tinode/webchat/issues/new).
* Use https://tinode.co/contact for commercial inquiries.
## Helping out
* If you appreciate our work, please help spread the word! Sharing on Reddit, HN, and other communities helps more than you think.
* Consider buying paid support: https://tinode.co/support.html
* If you are a software developer, send us your pull requests with bug fixes and new features.
* If you use the app and discover bugs or missing features, let us know by filing bug reports and feature requests. Vote for existing [feature requests](https://github.com/tinode/chat/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3A%22feature+request%22) you find most valuable.
* If you speak a language other than English, [translate](https://github.com/tinode/chat/blob/devel/docs/translations.md#webapp) the apps into your language. You may also review and improve existing translations.
* If you are a UI/UX expert, help us polish the app UI.
* Use it: install it for your colleagues or friends at work or at home.
## Internationalization
The app is fully internationalized using [React-Intl](https://github.com/formatjs/react-intl). The UI language is selected automatically from the language specified by the browser. A specific language can be forced by adding `#?hl=XX` parameter to the URL when starting the app, e.g. https://web.tinode.co/#?hl=fr.
The app is currently available in the following languages:
* English - default
* Arabic
* Chinese simplified
* Chinese traditional
* French
* German
* Italian
* Korean
* Romanian
* Russian
* Spanish
* Thai
* Ukrainian
* Vietnamese
More translations are welcome. See [instructions](https://github.com/tinode/chat/blob/devel/docs/translations.md#webapp).
## Not done yet
* End-to-End encryption.
* Emoji support is weak.
* Mentions, hashtags.
* Previews not generated for links and docs.
* Location and contact sharing.
* Recording video messages.
## Other
* Demo avatars and some other graphics are from https://www.pexels.com/ under [CC0 license](https://www.pexels.com/photo-license/).
* Background patterns from http://subtlepatterns.com/, commercial and non-commercial use allowed with attribution.
* [Fonts](https://fonts.google.com/) and [icons](https://google.github.io/material-design-icons/#icon-font-for-the-web) from Google under [license](https://developers.google.com/terms) which permits commercial and non-commercial use.
* Push notifications built with https://firebase.google.com/.
## Responsive design
### Desktop screenshot
<p align="center">
<img src="web-desktop.jpg" alt="Desktop web: full app" width=810 />
</p>
### Mobile screenshots
<p align="center">
<kbd><img src="web-mob-contacts.png" alt="Mobile web: contacts" width=250 /></kbd> <kbd><img src="web-mob-chat.png" alt="Mobile web: chat" width=250 /></kbd> <kbd><img src="web-mob-chat-dark.png" alt="Mobile web: chat dark mode" width=250 /></kbd> <kbd><img src="web-mob-info.png" alt="Mobile web: topic info" width=250 /></kbd> <kbd><img src="web-mob-forward.png" alt="Mobile web: forward message" width=250 /></kbd> <kbd><img src="web-mob-video-call.png" alt="Mobile web: video call" width=250 /></kbd>
</p>
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
-15171
View File
File diff suppressed because it is too large Load Diff
-1
View File
File diff suppressed because one or more lines are too long
-24
View File
@@ -1,24 +0,0 @@
server {
listen 80;
listen [::]:80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# The webapp uses real (History API) client-side routing, so any unknown path can safely fall
# back to index.html -- the app resolves the actual view/topic client-side from the path itself
# once index.html loads. index.html itself is never content-hashed, so it must always be
# revalidated -- otherwise a browser holding a cached copy would keep requesting the *previous*
# deploy's now-deleted /assets/*.js filenames after a new deploy replaces them.
location / {
add_header Cache-Control "no-cache";
try_files $uri $uri/ /index.html;
}
# Vite content-hashes every filename under assets/ (e.g. index-DYjopaLI.js) -- a new build never
# reuses an old asset's URL, so these can be cached aggressively and indefinitely; a stale cached
# copy simply never gets requested again once index.html points at the new hashed filenames.
location /assets/ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
}
-15
View File
@@ -1,15 +0,0 @@
// Get these values for your project from the https://console.firebase.google.com/
const FIREBASE_INIT = {
// Set up a web application in console then get the config object.
// The following keys are copied from the object:
apiKey: "AIzaSyD6X4ULR-RUsobvs1zZ2bHdJuPz39q2tbQ",
messagingSenderId: "114126160546",
projectId: "tinode-1000",
appId: "1:114126160546:web:aca6ea2981feb81fb44dfb",
// Project Settings -> Cloud Messaging -> Web configuration -> Web Push certificates.
// This value IS NOT included in the generated js config you get from
// the firebase console. It needs to be added separately.
messagingVapidKey: "BOgQVPOMzIMXUpsYGpbVkZoEBc0ifKY_f2kSU5DNDGYI6i6CoKqqxDd7w7PJ3FaGRBgVGJffldETumOx831jl58",
// Google analytics tag. Uncomment and use one you got from https://analytics.google.com/.
// measurementId: "G-ABCDEF1234"
};
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

-18
View File
@@ -1,18 +0,0 @@
{
"patt": [
{"name": "a00.png", "size": 200}, {"name": "a01.jpg", "size": 384}, {"name": "a02.jpg", "size": 384},
{"name": "a03.jpg", "size": 384}, {"name": "a04.png", "size": 400}, {"name": "a05.jpg", "size": 400},
{"name": "a06.jpg", "size": 256}, {"name": "a07.jpg", "size": 384}, {"name": "a08.jpg", "size": 384},
{"name": "a09.jpg", "size": 400}, {"name": "a10.jpg", "size": 256}, {"name": "a11.png", "size": 200}
],
"img": [
{"name": "w01.jpg", "pr": "p01.jpg"}, {"name": "w02.jpg", "pr": "p02.jpg"}, {"name": "w03.jpg", "pr": "p03.jpg"},
{"name": "w04.jpg", "pr": "p04.jpg"}, {"name": "w05.jpg", "pr": "p05.jpg"}, {"name": "w06.jpg", "pr": "p06.jpg"},
{"name": "w07.jpg", "pr": "p07.jpg"}, {"name": "w08.jpg", "pr": "p08.jpg"}, {"name": "w09.jpg", "pr": "p09.jpg"},
{"name": "w10.jpg", "pr": "p10.jpg"}, {"name": "w11.jpg", "pr": "p11.jpg"}, {"name": "w12.jpg", "pr": "p12.jpg"},
{"name": "w13.jpg", "pr": "p13.jpg"}, {"name": "w14.jpg", "pr": "p14.jpg"}, {"name": "w15.jpg", "pr": "p15.jpg"},
{"name": "w16.jpg", "pr": "p16.jpg"}, {"name": "w17.jpg", "pr": "p17.jpg"}, {"name": "w18.jpg", "pr": "p18.jpg"},
{"name": "w19.jpg", "pr": "p19.jpg"}, {"name": "w20.jpg", "pr": "p20.jpg"}, {"name": "w21.jpg", "pr": "p21.jpg"},
{"name": "w22.jpg", "pr": "p22.jpg"}, {"name": "w23.jpg", "pr": "p23.jpg"}, {"name": "w24.jpg", "pr": "p24.jpg"}
]
}
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 572 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 299 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 515 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 676 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 569 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 648 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 476 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 469 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 625 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 463 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 611 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 265 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 618 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 423 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 642 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 672 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 548 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 558 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 448 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 620 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

-9
View File
@@ -1,9 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 192">
<rect width="192" height="192" rx="26" fill="#ffffff"/>
<path transform="rotate(-18 96 96)" fill="#1677ff"
d="M96,13.5 A82.5,82.5 0 0 1 178.5,96 L178.5,96 A82.5,82.5 0 0 1 96,178.5 L43.2,178.5 A29.7,29.7 0 0 1 13.5,148.8 L13.5,96 A82.5,82.5 0 0 1 96,13.5 Z"/>
<text x="96" y="98" text-anchor="middle" dominant-baseline="central"
font-family="Roboto, Arial, sans-serif" font-weight="700" font-size="77" fill="#ffffff">M</text>
<circle cx="156" cy="156" r="30" fill="#ffffff"/>
<circle cx="156" cy="156" r="24" fill="#3ba55c"/>
</svg>

Before

Width:  |  Height:  |  Size: 614 B

-7
View File
@@ -1,7 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 192">
<rect width="192" height="192" rx="26" fill="#ffffff"/>
<path transform="rotate(-18 96 96)" fill="#1677ff"
d="M96,13.5 A82.5,82.5 0 0 1 178.5,96 L178.5,96 A82.5,82.5 0 0 1 96,178.5 L43.2,178.5 A29.7,29.7 0 0 1 13.5,148.8 L13.5,96 A82.5,82.5 0 0 1 96,13.5 Z"/>
<text x="96" y="98" text-anchor="middle" dominant-baseline="central"
font-family="Roboto, Arial, sans-serif" font-weight="700" font-size="77" fill="#ffffff">M</text>
</svg>

Before

Width:  |  Height:  |  Size: 510 B

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 938 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

-20
View File
@@ -1,20 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 750 500">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#1a2c52"/>
<stop offset="1" stop-color="#0e1730"/>
</linearGradient>
</defs>
<rect width="750" height="500" fill="url(#bg)"/>
<g transform="translate(375 168)">
<rect x="-70" y="-70" width="140" height="140" rx="19" fill="#ffffff"/>
<path transform="rotate(-18)" fill="#1677ff"
d="M0,-60 A60,60 0 0 1 60,0 L60,0 A60,60 0 0 1 0,60 L-38.4,60 A21.6,21.6 0 0 1 -60,38.4 L-60,0 A60,60 0 0 1 0,-60 Z"/>
<text x="0" y="2" text-anchor="middle" dominant-baseline="central"
font-family="Roboto, Arial, sans-serif" font-weight="700" font-size="56" fill="#ffffff">M</text>
</g>
<text x="375" y="345" text-anchor="middle"
font-family="Roboto, Arial, sans-serif" font-weight="700" font-size="56" fill="#ffffff">MeetingIM</text>
<text x="375" y="392" text-anchor="middle"
font-family="Roboto, Arial, sans-serif" font-weight="400" font-size="24" fill="#aab4c8">即时通讯</text>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

-1
View File
@@ -1 +0,0 @@
<svg height="24" viewBox="0 -960 960 960" width="24" fill="#5f6368" xmlns="http://www.w3.org/2000/svg"><path d="M197-706l-84-85 56-57 85 85zM791-112l-85-85 57-57 84 85zM0-440v-80h120v80zM840-440v-80h120v80zM169-113l-57-56 85-85 57 57zM763-706l-57-57 85-84 57 56zM440 0v-120h80V0zM440-840v-120h80v120zM743-380a766.09 766.09 0 01-39.5-11c-13-4-25.833-8.667-38.5-14 5.333-12 9.167-24.167 11.5-36.5 2.333-12.333 3.5-25.167 3.5-38.5 0-55.333-19.5-102.5-58.5-141.5S535.333-680 480-680c-13.333 0-26.167 1.167-38.5 3.5-12.333 2.333-24.5 6.167-36.5 11.5-5.333-12.667-9.833-25.333-13.5-38a1098.034 1098.034 0 01-10.5-39c16-6 32.333-10.5 49-13.5s33.667-4.5 51-4.5c78 0 144.167 27.167 198.5 81.5S761-558 761-480c0 17.333-1.5 34.333-4.5 51s-7.5 33-13.5 49z" fill="orange"/><path d="M453-452c34 34 72 63.167 114 87.5s87 43.167 135 56.5c-26.667 34-59.333 60.5-98 79.5S524.333-200 481-200c-78 0-144.167-27.167-198.5-81.5S201-402 201-480c0-43.333 9.5-84.333 28.5-123s45.5-71.333 79.5-98c13.333 48 32.167 93 56.5 135S419-486 453-452z" fill="#0c80d6"/></svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

-61
View File
@@ -1,61 +0,0 @@
<!-- DEVELOPMENT version of the web app. -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>MeetingIM</title>
<meta charset="utf-8" />
<!-- Real (History API) routing means the address bar can show a deep, multi-segment path like
/messages-home/grpXXX -- every asset reference below is a relative path (css/base.css,
umd/index.dev.js, etc.), which would otherwise resolve against that deep path instead of the
app's actual root on a deep-linked load or a refresh, 404ing everything. This pins relative
resolution to root regardless of the current path. -->
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="application-name" content="MeetingIM, version for developers" />
<meta name="description" content="MeetingIM instant messenger, development version" />
<meta name="application-url" content="https://web.118im.com/">
<!-- Browser styling for Chrome, FF, Opera -->
<meta name="theme-color" content="#3949AB" />
<!-- Ask Google not to offer page translation -->
<meta name="google" value="notranslate" />
<!-- Open Graph description -->
<meta name="og:url" content="https://web.118im.com/">
<meta name="og:title" content="MeetingIM Development">
<meta name="og:image" content="img/og-logo.jpeg">
<meta name="og:description" content="MeetingIM instant messenger, development version" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<link rel="manifest" href="manifest.json" />
<link rel="shortcut icon" id="shortcut-icon" href="img/logo32x32.png" type="image/png" />
<link rel="apple-touch-icon" sizes="192x192" href="img/logo192.png" type="image/png" />
<link rel="canonical" href="https://web.118im.com/" />
<!-- Google's Roboto font -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,500,700,700i" />
<!-- Google's material design icons -->
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
<!-- Styles for local elements -->
<link rel="stylesheet" href="css/base.css" />
<!-- Polyfill Intl.Segmenter for Firefox 124 and earlier. This can be safely removed in the end of 2024. -->
<script crossorigin="anonymous" src="https://polyfill-fastly.io/v3/polyfill.min.js?features=Intl.Segmenter"></script>
<!-- ReactJS -->
<script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/react@18/umd/react.development.js"></script>
<script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/react-dom@18/umd/react-dom.development.js"></script>
<!-- React-Intl for translations -->
<script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/react-intl@7/react-intl.iife.js"></script>
<!-- Displaying QR code with ID of the topic -->
<script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/qrcodejs@1.0.0/qrcode.js"></script>
</head>
<body>
<noscript><div id="noscript-message"><div id="noscript-title">Javascript support is required.</div>
<div id="noscript-content">It appears JavaScript is turned off or is not supported by your browser.
MeetingIM does not work without JavaScript. Please enable JavaScript by changing your browser options,
then <a href="">try again</a>.
</div>
</div></noscript>
<div id="mountPoint"></div>
<script src="firebase-init.js"></script>
<script src="umd/tinode.dev.js"></script>
<script src="umd/index.dev.js"></script>
</body>
</html>
-48
View File
@@ -1,48 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>MeetingIM</title>
<meta charset="utf-8" />
<!-- Real (History API) routing means the address bar can show a deep, multi-segment path like
/messages-home/grpXXX -- every asset reference below is a relative path (css/base.min.css,
umd/index.prod.js, etc.), which would otherwise resolve against that deep path instead of the
app's actual root on a deep-linked load or a refresh, 404ing everything. This pins relative
resolution to root regardless of the current path. -->
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="application-name" content="MeetingIM" />
<meta name="description" content="MeetingIM instant messenger in a browser" />
<meta name="application-url" content="https://web.118im.com/">
<meta name="theme-color" content="#3949AB" />
<meta name="google" value="notranslate" />
<meta name="format-detection" content="telephone=no" />
<meta name="og:url" content="https://web.118im.com/">
<meta name="og:title" content="MeetingIM">
<meta name="og:image" content="img/og-logo.jpeg">
<meta name="og:description" content="MeetingIM instant messenger in a browser" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<link rel="manifest" href="manifest.json" />
<link rel="shortcut icon" id="shortcut-icon" href="img/logo32x32.png" type="image/png" />
<link rel="apple-touch-icon" sizes="192x192" href="img/logo192.png" type="image/png" />
<link rel="canonical" href="https://web.118im.com/" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,500,700,700i" />
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
<link rel="stylesheet" href="css/base.min.css" />
<script crossorigin="anonymous" src="https://polyfill-fastly.io/v3/polyfill.min.js?features=Intl.Segmenter"></script>
<script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/react@18.3.1/umd/react.production.min.js"></script>
<script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/react-dom@18.3.1/umd/react-dom.production.min.js"></script>
<script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/react-intl@7.1.6/react-intl.iife.min.js"></script>
<script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/qrcodejs@1.0.0/qrcode.min.js"></script>
</head>
<body>
<noscript><div id="noscript-message"><div id="noscript-title">Javascript support is required.</div>
<div id="noscript-content">It appears JavaScript is turned off or is not supported by your browser.
MeetingIM does not work without JavaScript. Please enable JavaScript by changing your browser options,
then <a href="">try again</a>.</div></div></noscript>
<div id="mountPoint"></div>
<script src="firebase-init.js"></script>
<script src="umd/tinode.prod.js"></script>
<script src="umd/index.prod.js"></script>
</body>
</html>
-34
View File
@@ -1,34 +0,0 @@
{
"name": "MeetingIM",
"short_name": "MeetingIM",
"description": "MeetingIM instant messenger.",
"categories": ["chat", "communication", "productivity"],
"icons": [
{
"src":"img/logo96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src":"img/logo192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "img/logo.svg",
"type": "image/svg+xml",
"sizes": "512x512"
}
],
"start_url": "/",
"background_color": "silver",
"theme_color": "#3949AB",
"display": "standalone",
"gcm_sender_id": "103953800507",
"prefer_related_applications": false,
"permissions": {
"audio-capture": {
"description": "Required for recording voice messages"
}
}
}
-10826
View File
File diff suppressed because it is too large Load Diff
-115
View File
@@ -1,115 +0,0 @@
{
"name": "tinode-webapp",
"description": "Tinode messenger for the web",
"version": "0.25.3",
"repository": {
"type": "git",
"url": "git+https://github.com/tinode/webapp.git"
},
"scripts": {
"start": "echo 'Read installation instructions'",
"build": "npm run vers && npm run build:css && npm run extract && npm run build:i18n && npm run build:prod && npm run build:dev",
"clean": "rm umd/* && rm css/base.min.css && rm src/i18n.min/*",
"build:css": "postcss css/base.css > css/base.min.css",
"build:dev": "webpack --mode development",
"build:prod": "webpack --mode production",
"build:i18n": "node scripts/i18n.js",
"i18n:missing": "node scripts/i18n.js missing",
"i18n:obsolete": "node scripts/i18n.js obsolete",
"vers": "node scripts/gen-version.js",
"extract": "formatjs extract \"src/**/*.{js,jsx}\" --out-file src/i18n/ex/base-en.json --id-interpolation-pattern '[sha512:contenthash:base64:6]'",
"compile": "formatjs compile",
"test": "jest"
},
"browserslist": [
"defaults"
],
"overrides": {
"@babel/core": "^8.0.0"
},
"files": [
"umd/*.js",
"umd/*.map",
"audio/*.m4a",
"css/base.css",
"css/base.min.css",
"img/*.png",
"img/*.svg",
"img/*.jpeg",
"img/bkg/*.jpg",
"img/bkg/*.png",
"img/bkg/*.json",
"index-dev.html",
"index.html",
"manifest.json",
"service-worker.js",
"version.js"
],
"keywords": [
"chat",
"instant-messenger",
"message",
"messenger",
"react",
"web"
],
"locales": [
"ar",
"de",
"en",
"es",
"fr",
"it",
"ko",
"ro",
"ru",
"th",
"uk",
"vi",
"zh",
"zh-TW"
],
"main": "umd/index.prod.js",
"bugs": {
"url": "https://github.com/tinode/webapp/issues"
},
"homepage": "https://github.com/tinode/chat",
"email": "info@tinode.co",
"author": "Tinode Authors <info@tinode.co>",
"license": "Apache-2.0",
"dependencies": {
"firebase": "^12.15.0",
"jsqr": "^1.4.0",
"libphonenumber-js": "^1.10.40",
"pinyin-pro": "^3.29.3",
"qrcodejs": "^1.0.0",
"react": "^18.3.0",
"react-dom": "^18.3.0",
"react-intl": "^7.0.0",
"tinode-sdk": "^0.25.3",
"webm-duration-fix": "^1.0.4"
},
"devDependencies": {
"@babel/core": "^8.0.0",
"@babel/preset-env": "^8.0.0",
"@babel/preset-react": "^8.0.0",
"@formatjs/cli": "^6.1.3",
"babel-loader": "^10.0.0",
"babel-plugin-formatjs": "^11.0.0",
"browserslist": "^4.21.10",
"copy-webpack-plugin": "^14.0.0",
"cssnano": "^8.0.0",
"glob": "^13.0.0",
"jest": "^30.0.0",
"postcss": "^8.4.27",
"postcss-cli": "^11.0.0",
"webpack": "^5.88.2",
"webpack-cli": "^7.0.0"
},
"allowScripts": {
"@firebase/util@1.15.1": true,
"fsevents@2.3.3": true,
"protobufjs@7.6.5": true,
"unrs-resolver@1.12.2": true
}
}
-7
View File
@@ -1,7 +0,0 @@
module.exports = {
plugins: [
require('cssnano')({
preset: 'default',
}),
],
};
-11
View File
@@ -1,11 +0,0 @@
# Push notifications
If you want to use the app with your own server and want web push notification to work you have to set them up:
* Register at https://firebase.google.com/, set up the project if you have not done so already.
* Follow instructions to create a web application https://support.google.com/firebase/answer/9326094 in your project.
* Follow instructions at https://support.google.com/firebase/answer/7015592 to get a Firebase configuration object ("Firebase SDK snippet").
* Locate `firebase-init.js` in the root folder of your copy of TinodeWeb app. Copy-paste the following keys from the configuration object to `firebase-init.js`: `apiKey`, `messagingSenderId`, `projectId`, `appId` (you may copy all keys).
* Copy `Web Push certificate` (Project Settings -> Cloud Messaging -> Web configuration -> Web Push certificates) to `messagingVapidKey` field in `firebase-init.js`.
* Double check that `firebase-init.js` contains the following keys: `apiKey`, `messagingSenderId`, `projectId`, `appId`, `messagingVapidKey`. The file may contain other optional keys.
* Copy Google-provided server key to `tinode.conf`, see details [here](https://github.com/tinode/chat/blob/master/docs/faq.md#q-how-to-setup-fcm-push-notifications).

Some files were not shown because too many files have changed in this diff Show More