This commit is contained in:
OfficialDakari 2025-10-08 15:52:12 +05:00
commit 06d12c9e86
124 changed files with 4897 additions and 3081 deletions

View File

@ -1,4 +1,4 @@
#!/bin/sh
cd "$(dirname "$0")"
exec ./fluffychat
exec ./extera_next

View File

@ -0,0 +1 @@
extera.svg

4
appimage/Extera.AppDir/AppRun Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
cd "$(dirname "$0")"
exec ./extera_next

View File

@ -1,9 +1,9 @@
[Desktop Entry]
Type=Application
Version=1.0
Name=FluffyChat
Name=Extera Next
Comment=Matrix Client. Chat with your friends
Exec=AppRun
Icon=fluffychat
Icon=extera
Terminal=false
Categories=Network;Chat;InstantMessaging;X-Matrix;
Categories=Network;Chat;InstantMessaging;X-Matrix;

View File

@ -0,0 +1 @@
assets/banner.png  assetassets/banner.pngassets/banner_transparent.png  assetassets/banner_transparent.pngassets/favicon.png  assetassets/favicon.pngassets/info-logo.png  assetassets/info-logo.pngassets/js/olm.zip  assetassets/js/olm.zipassets/logo.png  assetassets/logo.pngassets/logo.svg  assetassets/logo.svgassets/logo_transparent.png  assetassets/logo_transparent.pngassets/sas-emoji.json  assetassets/sas-emoji.jsonassets/sounds/call.ogg  assetassets/sounds/call.oggassets/sounds/notification.ogg  assetassets/sounds/notification.oggassets/sounds/phone.ogg  assetassets/sounds/phone.ogg2packages/cupertino_icons/assets/CupertinoIcons.ttf  asset2packages/cupertino_icons/assets/CupertinoIcons.ttf4packages/flutter_map/lib/assets/flutter_map_logo.png  asset4packages/flutter_map/lib/assets/flutter_map_logo.png2packages/handy_window/assets/handy-window-dark.css  asset2packages/handy_window/assets/handy-window-dark.css-packages/handy_window/assets/handy-window.css  asset-packages/handy_window/assets/handy-window.css(packages/material/lib/fonts/material.ttf  asset(packages/material/lib/fonts/material.ttf7packages/record_web/assets/js/record.fixwebmduration.js  asset7packages/record_web/assets/js/record.fixwebmduration.js/packages/record_web/assets/js/record.worklet.js  asset/packages/record_web/assets/js/record.worklet.js)packages/wakelock_plus/assets/no_sleep.js  asset)packages/wakelock_plus/assets/no_sleep.js

View File

@ -0,0 +1 @@
{"assets/banner.png":["assets/banner.png"],"assets/banner_transparent.png":["assets/banner_transparent.png"],"assets/favicon.png":["assets/favicon.png"],"assets/info-logo.png":["assets/info-logo.png"],"assets/js/olm.zip":["assets/js/olm.zip"],"assets/logo.png":["assets/logo.png"],"assets/logo.svg":["assets/logo.svg"],"assets/logo_transparent.png":["assets/logo_transparent.png"],"assets/sas-emoji.json":["assets/sas-emoji.json"],"assets/sounds/call.ogg":["assets/sounds/call.ogg"],"assets/sounds/notification.ogg":["assets/sounds/notification.ogg"],"assets/sounds/phone.ogg":["assets/sounds/phone.ogg"],"packages/cupertino_icons/assets/CupertinoIcons.ttf":["packages/cupertino_icons/assets/CupertinoIcons.ttf"],"packages/flutter_map/lib/assets/flutter_map_logo.png":["packages/flutter_map/lib/assets/flutter_map_logo.png"],"packages/handy_window/assets/handy-window-dark.css":["packages/handy_window/assets/handy-window-dark.css"],"packages/handy_window/assets/handy-window.css":["packages/handy_window/assets/handy-window.css"],"packages/material/lib/fonts/material.ttf":["packages/material/lib/fonts/material.ttf"],"packages/record_web/assets/js/record.fixwebmduration.js":["packages/record_web/assets/js/record.fixwebmduration.js"],"packages/record_web/assets/js/record.worklet.js":["packages/record_web/assets/js/record.worklet.js"],"packages/wakelock_plus/assets/no_sleep.js":["packages/wakelock_plus/assets/no_sleep.js"]}

View File

@ -0,0 +1 @@
[{"family":"MaterialIcons","fonts":[{"asset":"fonts/MaterialIcons-Regular.otf"}]},{"family":"packages/material/Material","fonts":[{"asset":"packages/material/lib/fonts/material.ttf"}]},{"family":"packages/cupertino_icons/CupertinoIcons","fonts":[{"asset":"packages/cupertino_icons/assets/CupertinoIcons.ttf"}]}]

Binary file not shown.

View File

@ -0,0 +1 @@
{"format-version":[1,0,0],"native-assets":{}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1 @@
Not Found

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,11 @@
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 70.82 81.78">
<defs>
<linearGradient id="a" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="#406FBF" />
<stop offset="100%" stop-color="#23509D" />
</linearGradient>
</defs>
<path fill-rule="evenodd"
d="M70.82 44.98v16.36l-17.7 10.22-17.71 10.22-2.59-1.5L0 61.34V20.45l17.7-10.23L35.41 0l28.33 16.36 4.49 2.59 2.59 1.5v8.17L35.41 49.07l-7.08-4.09V36.8l21.25-12.27-14.17-8.17-21.25 12.26v24.54l21.25 12.26.03.02.02-.05z"
style="fill:url(#a)" />
</svg>

After

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1 @@
window{background-color:#252525}window.csd.unified decoration-overlay{box-shadow:none}window.csd.unified:not(.solid-csd):not(.fullscreen):not(.maximized) decoration-overlay{box-shadow:inset 0 0 0 1px rgba(255,255,255,.07)}window.csd.unified decoration{box-shadow:0 3px 9px 1px rgba(0,0,0,.5)}window.csd.unified decoration:backdrop{box-shadow:0 3px 9px 1px rgba(0,0,0,0),0 2px 6px 2px rgba(0,0,0,.2)}headerbar{min-height:47px;background:#303030;box-shadow:inset 0 -1px rgba(0,0,0,.36);border:none}headerbar:backdrop{background:#242424}button.titlebutton{padding:4px;margin:1px}

View File

@ -0,0 +1 @@
window{background-color:#fff}window.csd.unified decoration-overlay{box-shadow:none}window.csd.unified:not(.solid-csd):not(.fullscreen):not(.maximized) decoration-overlay{box-shadow:inset 0 0 0 1px rgba(255,255,255,.07)}window.csd.unified decoration{box-shadow:0 3px 9px 1px rgba(0,0,0,.5)}window.csd.unified decoration:backdrop{box-shadow:0 3px 9px 1px rgba(0,0,0,0),0 2px 6px 2px rgba(0,0,0,.2)}headerbar{min-height:47px;background:#ebebeb;box-shadow:inset 0 -1px rgba(0,0,0,.07);border:none}headerbar:backdrop{background:#fafafa}button.titlebutton{padding:4px;margin:1px}

View File

@ -0,0 +1,507 @@
(function (name, definition) {
window.jsFixWebmDuration = definition();
})('fix-webm-duration', function () {
/*
* This is the list of possible WEBM file sections by their IDs.
* Possible types: Container, Binary, Uint, Int, String, Float, Date
*/
var sections = {
0xa45dfa3: { name: 'EBML', type: 'Container' },
0x286: { name: 'EBMLVersion', type: 'Uint' },
0x2f7: { name: 'EBMLReadVersion', type: 'Uint' },
0x2f2: { name: 'EBMLMaxIDLength', type: 'Uint' },
0x2f3: { name: 'EBMLMaxSizeLength', type: 'Uint' },
0x282: { name: 'DocType', type: 'String' },
0x287: { name: 'DocTypeVersion', type: 'Uint' },
0x285: { name: 'DocTypeReadVersion', type: 'Uint' },
0x6c: { name: 'Void', type: 'Binary' },
0x3f: { name: 'CRC-32', type: 'Binary' },
0xb538667: { name: 'SignatureSlot', type: 'Container' },
0x3e8a: { name: 'SignatureAlgo', type: 'Uint' },
0x3e9a: { name: 'SignatureHash', type: 'Uint' },
0x3ea5: { name: 'SignaturePublicKey', type: 'Binary' },
0x3eb5: { name: 'Signature', type: 'Binary' },
0x3e5b: { name: 'SignatureElements', type: 'Container' },
0x3e7b: { name: 'SignatureElementList', type: 'Container' },
0x2532: { name: 'SignedElement', type: 'Binary' },
0x8538067: { name: 'Segment', type: 'Container' },
0x14d9b74: { name: 'SeekHead', type: 'Container' },
0xdbb: { name: 'Seek', type: 'Container' },
0x13ab: { name: 'SeekID', type: 'Binary' },
0x13ac: { name: 'SeekPosition', type: 'Uint' },
0x549a966: { name: 'Info', type: 'Container' },
0x33a4: { name: 'SegmentUID', type: 'Binary' },
0x3384: { name: 'SegmentFilename', type: 'String' },
0x1cb923: { name: 'PrevUID', type: 'Binary' },
0x1c83ab: { name: 'PrevFilename', type: 'String' },
0x1eb923: { name: 'NextUID', type: 'Binary' },
0x1e83bb: { name: 'NextFilename', type: 'String' },
0x444: { name: 'SegmentFamily', type: 'Binary' },
0x2924: { name: 'ChapterTranslate', type: 'Container' },
0x29fc: { name: 'ChapterTranslateEditionUID', type: 'Uint' },
0x29bf: { name: 'ChapterTranslateCodec', type: 'Uint' },
0x29a5: { name: 'ChapterTranslateID', type: 'Binary' },
0xad7b1: { name: 'TimecodeScale', type: 'Uint' },
0x489: { name: 'Duration', type: 'Float' },
0x461: { name: 'DateUTC', type: 'Date' },
0x3ba9: { name: 'Title', type: 'String' },
0xd80: { name: 'MuxingApp', type: 'String' },
0x1741: { name: 'WritingApp', type: 'String' },
// 0xf43b675: { name: 'Cluster', type: 'Container' },
0x67: { name: 'Timecode', type: 'Uint' },
0x1854: { name: 'SilentTracks', type: 'Container' },
0x18d7: { name: 'SilentTrackNumber', type: 'Uint' },
0x27: { name: 'Position', type: 'Uint' },
0x2b: { name: 'PrevSize', type: 'Uint' },
0x23: { name: 'SimpleBlock', type: 'Binary' },
0x20: { name: 'BlockGroup', type: 'Container' },
0x21: { name: 'Block', type: 'Binary' },
0x22: { name: 'BlockVirtual', type: 'Binary' },
0x35a1: { name: 'BlockAdditions', type: 'Container' },
0x26: { name: 'BlockMore', type: 'Container' },
0x6e: { name: 'BlockAddID', type: 'Uint' },
0x25: { name: 'BlockAdditional', type: 'Binary' },
0x1b: { name: 'BlockDuration', type: 'Uint' },
0x7a: { name: 'ReferencePriority', type: 'Uint' },
0x7b: { name: 'ReferenceBlock', type: 'Int' },
0x7d: { name: 'ReferenceVirtual', type: 'Int' },
0x24: { name: 'CodecState', type: 'Binary' },
0x35a2: { name: 'DiscardPadding', type: 'Int' },
0xe: { name: 'Slices', type: 'Container' },
0x68: { name: 'TimeSlice', type: 'Container' },
0x4c: { name: 'LaceNumber', type: 'Uint' },
0x4d: { name: 'FrameNumber', type: 'Uint' },
0x4b: { name: 'BlockAdditionID', type: 'Uint' },
0x4e: { name: 'Delay', type: 'Uint' },
0x4f: { name: 'SliceDuration', type: 'Uint' },
0x48: { name: 'ReferenceFrame', type: 'Container' },
0x49: { name: 'ReferenceOffset', type: 'Uint' },
0x4a: { name: 'ReferenceTimeCode', type: 'Uint' },
0x2f: { name: 'EncryptedBlock', type: 'Binary' },
0x654ae6b: { name: 'Tracks', type: 'Container' },
0x2e: { name: 'TrackEntry', type: 'Container' },
0x57: { name: 'TrackNumber', type: 'Uint' },
0x33c5: { name: 'TrackUID', type: 'Uint' },
0x3: { name: 'TrackType', type: 'Uint' },
0x39: { name: 'FlagEnabled', type: 'Uint' },
0x8: { name: 'FlagDefault', type: 'Uint' },
0x15aa: { name: 'FlagForced', type: 'Uint' },
0x1c: { name: 'FlagLacing', type: 'Uint' },
0x2de7: { name: 'MinCache', type: 'Uint' },
0x2df8: { name: 'MaxCache', type: 'Uint' },
0x3e383: { name: 'DefaultDuration', type: 'Uint' },
0x34e7a: { name: 'DefaultDecodedFieldDuration', type: 'Uint' },
0x3314f: { name: 'TrackTimecodeScale', type: 'Float' },
0x137f: { name: 'TrackOffset', type: 'Int' },
0x15ee: { name: 'MaxBlockAdditionID', type: 'Uint' },
0x136e: { name: 'Name', type: 'String' },
0x2b59c: { name: 'Language', type: 'String' },
0x6: { name: 'CodecID', type: 'String' },
0x23a2: { name: 'CodecPrivate', type: 'Binary' },
0x58688: { name: 'CodecName', type: 'String' },
0x3446: { name: 'AttachmentLink', type: 'Uint' },
0x1a9697: { name: 'CodecSettings', type: 'String' },
0x1b4040: { name: 'CodecInfoURL', type: 'String' },
0x6b240: { name: 'CodecDownloadURL', type: 'String' },
0x2a: { name: 'CodecDecodeAll', type: 'Uint' },
0x2fab: { name: 'TrackOverlay', type: 'Uint' },
0x16aa: { name: 'CodecDelay', type: 'Uint' },
0x16bb: { name: 'SeekPreRoll', type: 'Uint' },
0x2624: { name: 'TrackTranslate', type: 'Container' },
0x26fc: { name: 'TrackTranslateEditionUID', type: 'Uint' },
0x26bf: { name: 'TrackTranslateCodec', type: 'Uint' },
0x26a5: { name: 'TrackTranslateTrackID', type: 'Binary' },
0x60: { name: 'Video', type: 'Container' },
0x1a: { name: 'FlagInterlaced', type: 'Uint' },
0x13b8: { name: 'StereoMode', type: 'Uint' },
0x13c0: { name: 'AlphaMode', type: 'Uint' },
0x13b9: { name: 'OldStereoMode', type: 'Uint' },
0x30: { name: 'PixelWidth', type: 'Uint' },
0x3a: { name: 'PixelHeight', type: 'Uint' },
0x14aa: { name: 'PixelCropBottom', type: 'Uint' },
0x14bb: { name: 'PixelCropTop', type: 'Uint' },
0x14cc: { name: 'PixelCropLeft', type: 'Uint' },
0x14dd: { name: 'PixelCropRight', type: 'Uint' },
0x14b0: { name: 'DisplayWidth', type: 'Uint' },
0x14ba: { name: 'DisplayHeight', type: 'Uint' },
0x14b2: { name: 'DisplayUnit', type: 'Uint' },
0x14b3: { name: 'AspectRatioType', type: 'Uint' },
0xeb524: { name: 'ColourSpace', type: 'Binary' },
0xfb523: { name: 'GammaValue', type: 'Float' },
0x383e3: { name: 'FrameRate', type: 'Float' },
0x61: { name: 'Audio', type: 'Container' },
0x35: { name: 'SamplingFrequency', type: 'Float' },
0x38b5: { name: 'OutputSamplingFrequency', type: 'Float' },
0x1f: { name: 'Channels', type: 'Uint' },
0x3d7b: { name: 'ChannelPositions', type: 'Binary' },
0x2264: { name: 'BitDepth', type: 'Uint' },
0x62: { name: 'TrackOperation', type: 'Container' },
0x63: { name: 'TrackCombinePlanes', type: 'Container' },
0x64: { name: 'TrackPlane', type: 'Container' },
0x65: { name: 'TrackPlaneUID', type: 'Uint' },
0x66: { name: 'TrackPlaneType', type: 'Uint' },
0x69: { name: 'TrackJoinBlocks', type: 'Container' },
0x6d: { name: 'TrackJoinUID', type: 'Uint' },
0x40: { name: 'TrickTrackUID', type: 'Uint' },
0x41: { name: 'TrickTrackSegmentUID', type: 'Binary' },
0x46: { name: 'TrickTrackFlag', type: 'Uint' },
0x47: { name: 'TrickMasterTrackUID', type: 'Uint' },
0x44: { name: 'TrickMasterTrackSegmentUID', type: 'Binary' },
0x2d80: { name: 'ContentEncodings', type: 'Container' },
0x2240: { name: 'ContentEncoding', type: 'Container' },
0x1031: { name: 'ContentEncodingOrder', type: 'Uint' },
0x1032: { name: 'ContentEncodingScope', type: 'Uint' },
0x1033: { name: 'ContentEncodingType', type: 'Uint' },
0x1034: { name: 'ContentCompression', type: 'Container' },
0x254: { name: 'ContentCompAlgo', type: 'Uint' },
0x255: { name: 'ContentCompSettings', type: 'Binary' },
0x1035: { name: 'ContentEncryption', type: 'Container' },
0x7e1: { name: 'ContentEncAlgo', type: 'Uint' },
0x7e2: { name: 'ContentEncKeyID', type: 'Binary' },
0x7e3: { name: 'ContentSignature', type: 'Binary' },
0x7e4: { name: 'ContentSigKeyID', type: 'Binary' },
0x7e5: { name: 'ContentSigAlgo', type: 'Uint' },
0x7e6: { name: 'ContentSigHashAlgo', type: 'Uint' },
0xc53bb6b: { name: 'Cues', type: 'Container' },
0x3b: { name: 'CuePoint', type: 'Container' },
0x33: { name: 'CueTime', type: 'Uint' },
0x37: { name: 'CueTrackPositions', type: 'Container' },
0x77: { name: 'CueTrack', type: 'Uint' },
0x71: { name: 'CueClusterPosition', type: 'Uint' },
0x70: { name: 'CueRelativePosition', type: 'Uint' },
0x32: { name: 'CueDuration', type: 'Uint' },
0x1378: { name: 'CueBlockNumber', type: 'Uint' },
0x6a: { name: 'CueCodecState', type: 'Uint' },
0x5b: { name: 'CueReference', type: 'Container' },
0x16: { name: 'CueRefTime', type: 'Uint' },
0x17: { name: 'CueRefCluster', type: 'Uint' },
0x135f: { name: 'CueRefNumber', type: 'Uint' },
0x6b: { name: 'CueRefCodecState', type: 'Uint' },
0x941a469: { name: 'Attachments', type: 'Container' },
0x21a7: { name: 'AttachedFile', type: 'Container' },
0x67e: { name: 'FileDescription', type: 'String' },
0x66e: { name: 'FileName', type: 'String' },
0x660: { name: 'FileMimeType', type: 'String' },
0x65c: { name: 'FileData', type: 'Binary' },
0x6ae: { name: 'FileUID', type: 'Uint' },
0x675: { name: 'FileReferral', type: 'Binary' },
0x661: { name: 'FileUsedStartTime', type: 'Uint' },
0x662: { name: 'FileUsedEndTime', type: 'Uint' },
0x43a770: { name: 'Chapters', type: 'Container' },
0x5b9: { name: 'EditionEntry', type: 'Container' },
0x5bc: { name: 'EditionUID', type: 'Uint' },
0x5bd: { name: 'EditionFlagHidden', type: 'Uint' },
0x5db: { name: 'EditionFlagDefault', type: 'Uint' },
0x5dd: { name: 'EditionFlagOrdered', type: 'Uint' },
0x36: { name: 'ChapterAtom', type: 'Container' },
0x33c4: { name: 'ChapterUID', type: 'Uint' },
0x1654: { name: 'ChapterStringUID', type: 'String' },
0x11: { name: 'ChapterTimeStart', type: 'Uint' },
0x12: { name: 'ChapterTimeEnd', type: 'Uint' },
0x18: { name: 'ChapterFlagHidden', type: 'Uint' },
0x598: { name: 'ChapterFlagEnabled', type: 'Uint' },
0x2e67: { name: 'ChapterSegmentUID', type: 'Binary' },
0x2ebc: { name: 'ChapterSegmentEditionUID', type: 'Uint' },
0x23c3: { name: 'ChapterPhysicalEquiv', type: 'Uint' },
0xf: { name: 'ChapterTrack', type: 'Container' },
0x9: { name: 'ChapterTrackNumber', type: 'Uint' },
0x0: { name: 'ChapterDisplay', type: 'Container' },
0x5: { name: 'ChapString', type: 'String' },
0x37c: { name: 'ChapLanguage', type: 'String' },
0x37e: { name: 'ChapCountry', type: 'String' },
0x2944: { name: 'ChapProcess', type: 'Container' },
0x2955: { name: 'ChapProcessCodecID', type: 'Uint' },
0x50d: { name: 'ChapProcessPrivate', type: 'Binary' },
0x2911: { name: 'ChapProcessCommand', type: 'Container' },
0x2922: { name: 'ChapProcessTime', type: 'Uint' },
0x2933: { name: 'ChapProcessData', type: 'Binary' },
0x254c367: { name: 'Tags', type: 'Container' },
0x3373: { name: 'Tag', type: 'Container' },
0x23c0: { name: 'Targets', type: 'Container' },
0x28ca: { name: 'TargetTypeValue', type: 'Uint' },
0x23ca: { name: 'TargetType', type: 'String' },
0x23c5: { name: 'TagTrackUID', type: 'Uint' },
0x23c9: { name: 'TagEditionUID', type: 'Uint' },
0x23c4: { name: 'TagChapterUID', type: 'Uint' },
0x23c6: { name: 'TagAttachmentUID', type: 'Uint' },
0x27c8: { name: 'SimpleTag', type: 'Container' },
0x5a3: { name: 'TagName', type: 'String' },
0x47a: { name: 'TagLanguage', type: 'String' },
0x484: { name: 'TagDefault', type: 'Uint' },
0x487: { name: 'TagString', type: 'String' },
0x485: { name: 'TagBinary', type: 'Binary' }
};
function doInherit(newClass, baseClass) {
newClass.prototype = Object.create(baseClass.prototype);
newClass.prototype.constructor = newClass;
}
function WebmBase(name, type) {
this.name = name || 'Unknown';
this.type = type || 'Unknown';
}
WebmBase.prototype.updateBySource = function () { };
WebmBase.prototype.setSource = function (source) {
this.source = source;
this.updateBySource();
};
WebmBase.prototype.updateByData = function () { };
WebmBase.prototype.setData = function (data) {
this.data = data;
this.updateByData();
};
function WebmUint(name, type) {
WebmBase.call(this, name, type || 'Uint');
}
doInherit(WebmUint, WebmBase);
function padHex(hex) {
return hex.length % 2 === 1 ? '0' + hex : hex;
}
WebmUint.prototype.updateBySource = function () {
// use hex representation of a number instead of number value
this.data = '';
for (var i = 0; i < this.source.length; i++) {
var hex = this.source[i].toString(16);
this.data += padHex(hex);
}
};
WebmUint.prototype.updateByData = function () {
var length = this.data.length / 2;
this.source = new Uint8Array(length);
for (var i = 0; i < length; i++) {
var hex = this.data.substr(i * 2, 2);
this.source[i] = parseInt(hex, 16);
}
};
WebmUint.prototype.getValue = function () {
return parseInt(this.data, 16);
};
WebmUint.prototype.setValue = function (value) {
this.setData(padHex(value.toString(16)));
};
function WebmFloat(name, type) {
WebmBase.call(this, name, type || 'Float');
}
doInherit(WebmFloat, WebmBase);
WebmFloat.prototype.getFloatArrayType = function () {
return this.source && this.source.length === 4 ? Float32Array : Float64Array;
};
WebmFloat.prototype.updateBySource = function () {
var byteArray = this.source.reverse();
var floatArrayType = this.getFloatArrayType();
var floatArray = new floatArrayType(byteArray.buffer);
this.data = floatArray[0];
};
WebmFloat.prototype.updateByData = function () {
var floatArrayType = this.getFloatArrayType();
var floatArray = new floatArrayType([this.data]);
var byteArray = new Uint8Array(floatArray.buffer);
this.source = byteArray.reverse();
};
WebmFloat.prototype.getValue = function () {
return this.data;
};
WebmFloat.prototype.setValue = function (value) {
this.setData(value);
};
function WebmContainer(name, type) {
WebmBase.call(this, name, type || 'Container');
}
doInherit(WebmContainer, WebmBase);
WebmContainer.prototype.readByte = function () {
return this.source[this.offset++];
};
WebmContainer.prototype.readUint = function () {
var firstByte = this.readByte();
var bytes = 8 - firstByte.toString(2).length;
var value = firstByte - (1 << (7 - bytes));
for (var i = 0; i < bytes; i++) {
// don't use bit operators to support x86
value *= 256;
value += this.readByte();
}
return value;
};
WebmContainer.prototype.updateBySource = function () {
this.data = [];
for (this.offset = 0; this.offset < this.source.length; this.offset = end) {
var id = this.readUint();
var len = this.readUint();
var end = Math.min(this.offset + len, this.source.length);
var data = this.source.slice(this.offset, end);
var info = sections[id] || { name: 'Unknown', type: 'Unknown' };
var ctr = WebmBase;
switch (info.type) {
case 'Container':
ctr = WebmContainer;
break;
case 'Uint':
ctr = WebmUint;
break;
case 'Float':
ctr = WebmFloat;
break;
}
var section = new ctr(info.name, info.type);
section.setSource(data);
this.data.push({
id: id,
idHex: id.toString(16),
data: section
});
}
};
WebmContainer.prototype.writeUint = function (x, draft) {
for (var bytes = 1, flag = 0x80; x >= flag && bytes < 8; bytes++, flag *= 0x80) { }
if (!draft) {
var value = flag + x;
for (var i = bytes - 1; i >= 0; i--) {
// don't use bit operators to support x86
var c = value % 256;
this.source[this.offset + i] = c;
value = (value - c) / 256;
}
}
this.offset += bytes;
};
WebmContainer.prototype.writeSections = function (draft) {
this.offset = 0;
for (var i = 0; i < this.data.length; i++) {
var section = this.data[i],
content = section.data.source,
contentLength = content.length;
this.writeUint(section.id, draft);
this.writeUint(contentLength, draft);
if (!draft) {
this.source.set(content, this.offset);
}
this.offset += contentLength;
}
return this.offset;
};
WebmContainer.prototype.updateByData = function () {
// run without accessing this.source to determine total length - need to know it to create Uint8Array
var length = this.writeSections('draft');
this.source = new Uint8Array(length);
// now really write data
this.writeSections();
};
WebmContainer.prototype.getSectionById = function (id) {
for (var i = 0; i < this.data.length; i++) {
var section = this.data[i];
if (section.id === id) {
return section.data;
}
}
return null;
};
function WebmFile(source) {
WebmContainer.call(this, 'File', 'File');
this.setSource(source);
}
doInherit(WebmFile, WebmContainer);
WebmFile.prototype.fixDuration = function (duration, options) {
var logger = options && options.logger;
if (logger === undefined) {
logger = function (message) {
console.log(message);
};
} else if (!logger) {
logger = function () { };
}
var segmentSection = this.getSectionById(0x8538067);
if (!segmentSection) {
logger('[fix-webm-duration] Segment section is missing');
return false;
}
var infoSection = segmentSection.getSectionById(0x549a966);
if (!infoSection) {
logger('[fix-webm-duration] Info section is missing');
return false;
}
var timeScaleSection = infoSection.getSectionById(0xad7b1);
if (!timeScaleSection) {
logger('[fix-webm-duration] TimecodeScale section is missing');
return false;
}
var durationSection = infoSection.getSectionById(0x489);
if (durationSection) {
if (durationSection.getValue() <= 0) {
logger('[fix-webm-duration] Duration section is present, but the value is empty. Applying ' + duration.toLocaleString() + ' ms.');
durationSection.setValue(duration);
} else {
logger('[fix-webm-duration] Duration section is present');
return false;
}
} else {
logger('[fix-webm-duration] Duration section is missing. Applying ' + duration.toLocaleString() + ' ms.');
// append Duration section
durationSection = new WebmFloat('Duration', 'Float');
durationSection.setValue(duration);
infoSection.data.push({
id: 0x489,
data: durationSection
});
}
// set default time scale to 1 millisecond (1000000 nanoseconds)
timeScaleSection.setValue(1000000);
infoSection.updateByData();
segmentSection.updateByData();
this.updateByData();
return true;
};
WebmFile.prototype.toBlob = function (mimeType) {
return new Blob([this.source.buffer], { type: mimeType || 'audio/webm' });
};
function fixWebmDuration(blob, duration, callback, options) {
// The callback may be omitted - then the third argument is options
if (typeof callback === "object") {
options = callback;
callback = undefined;
}
if (!callback) {
return new Promise(function (resolve) {
fixWebmDuration(blob, duration, resolve, options);
});
}
try {
var reader = new FileReader();
reader.onloadend = function () {
try {
var file = new WebmFile(new Uint8Array(reader.result));
if (file.fixDuration(duration, options)) {
blob = file.toBlob(blob.type);
}
} catch (ex) {
// ignore
}
callback(blob);
};
reader.readAsArrayBuffer(blob);
} catch (ex) {
callback(blob);
}
}
// Support AMD import default
fixWebmDuration.default = fixWebmDuration;
return fixWebmDuration;
});

View File

@ -0,0 +1,400 @@
class RecorderProcessor extends AudioWorkletProcessor {
static get parameterDescriptors() {
return [
{
name: 'numChannels',
defaultValue: 1,
minValue: 1,
maxValue: 16
},
{
name: 'sampleRate',
defaultValue: 48000,
minValue: 8000,
maxValue: 96000
}
];
}
// Buffer size compromise between size and process call frequency
_bufferSize = 4096
// The current buffer fill level
_bytesWritten = 0
// Buffer per channel
_buffers = []
// Resampler (passthrough, down or up)
_resampler = null
// Config
_numChannels = 1
_sampleRate = 48000
constructor(options) {
super(options)
this._numChannels = options.parameterData.numChannels
this._sampleRate = options.parameterData.sampleRate
// Resampler(current context sample rate, desired sample rate, num channels, buffer size)
// num channels is always 1 since we resample after interleaving channels
this._resampler = new Resampler(sampleRate, this._sampleRate, 1, this._bufferSize * this._numChannels)
this.initBuffers()
}
initBuffers() {
this._bytesWritten = 0
this._buffers = []
for (let channel = 0; channel < this._numChannels; channel++) {
this._buffers[channel] = []
}
}
/**
* @returns {boolean}
*/
isBufferEmpty() {
return this._bytesWritten === 0
}
/**
* @returns {boolean}
*/
isBufferFull() {
return this._bytesWritten >= this._bufferSize
}
/**
* @param {Float32Array[][]} inputs
* @returns {boolean}
*/
process(inputs) {
if (this.isBufferFull()) {
this.flush()
}
const input = inputs[0]
if (input.length == 0) {
// Sometimes, Firefox doesn't give any input. Skip this frame to not fail.
return true
}
for (let channel = 0; channel < this._numChannels; channel++) {
// Push a copy of the array.
// The underlying implementation may reuse it which will break the recording.
this._buffers[channel].push([...input[channel]])
}
this._bytesWritten += input[0].length
return true
}
flush() {
let channels = []
for (let channel = 0; channel < this._numChannels; channel++) {
channels.push(this.mergeFloat32Arrays(this._buffers[channel], this._bytesWritten))
}
let interleaved = this.interleave(channels)
let resampled = this._resampler.resample(interleaved)
this.port.postMessage(this.floatTo16BitPCM(resampled))
this.initBuffers()
}
mergeFloat32Arrays(arrays, bytesWritten) {
let result = new Float32Array(bytesWritten)
var offset = 0
for (let i = 0; i < arrays.length; i++) {
result.set(arrays[i], offset)
offset += arrays[i].length
}
return result
}
// Interleave data from channels from LLLLRRRR to LRLRLRLR
interleave(channels) {
if (channels === 1) {
return channels[0]
}
var length = 0
for (let i = 0; i < channels.length; i++) {
length += channels[i].length
}
let result = new Float32Array(length)
var index = 0
var inputIndex = 0
while (index < length) {
for (let i = 0; i < channels.length; i++) {
result[index] = channels[i][inputIndex]
index++
}
inputIndex++
}
return result
}
floatTo16BitPCM(input) {
let output = new DataView(new ArrayBuffer(input.length * 2))
for (let i = 0; i < input.length; i++) {
let s = Math.max(-1, Math.min(1, input[i]))
let s16 = s < 0 ? s * 0x8000 : s * 0x7FFF
output.setInt16(i * 2, s16, true)
}
return new Int16Array(output.buffer)
}
}
class Resampler {
constructor(fromSampleRate, toSampleRate, channels, inputBufferSize) {
if (!fromSampleRate || !toSampleRate || !channels) {
throw (new Error("Invalid settings specified for the resampler."));
}
this.resampler = null;
this.fromSampleRate = fromSampleRate;
this.toSampleRate = toSampleRate;
this.channels = channels || 0;
this.inputBufferSize = inputBufferSize;
this.initialize()
}
initialize() {
if (this.fromSampleRate == this.toSampleRate) {
// Setup resampler bypass - Resampler just returns what was passed through
this.resampler = (buffer) => {
return buffer
};
this.ratioWeight = 1;
} else {
if (this.fromSampleRate < this.toSampleRate) {
// Use generic linear interpolation if upsampling,
// as linear interpolation produces a gradient that we want
// and works fine with two input sample points per output in this case.
this.linearInterpolation();
this.lastWeight = 1;
} else {
// Custom resampler I wrote that doesn't skip samples
// like standard linear interpolation in high downsampling.
// This is more accurate than linear interpolation on downsampling.
this.multiTap();
this.tailExists = false;
this.lastWeight = 0;
}
// Initialize the internal buffer:
this.initializeBuffers();
this.ratioWeight = this.fromSampleRate / this.toSampleRate;
}
}
bufferSlice(sliceAmount) {
//Typed array and normal array buffer section referencing:
try {
return this.outputBuffer.subarray(0, sliceAmount);
}
catch (error) {
try {
//Regular array pass:
this.outputBuffer.length = sliceAmount;
return this.outputBuffer;
}
catch (error) {
//Nightly Firefox 4 used to have the subarray function named as slice:
return this.outputBuffer.slice(0, sliceAmount);
}
}
}
initializeBuffers() {
this.outputBufferSize = (Math.ceil(this.inputBufferSize * this.toSampleRate / this.fromSampleRate / this.channels * 1.000000476837158203125) + this.channels) + this.channels;
try {
this.outputBuffer = new Float32Array(this.outputBufferSize);
this.lastOutput = new Float32Array(this.channels);
}
catch (error) {
this.outputBuffer = [];
this.lastOutput = [];
}
}
linearInterpolation() {
this.resampler = (buffer) => {
let bufferLength = buffer.length,
channels = this.channels,
outLength,
ratioWeight,
weight,
firstWeight,
secondWeight,
sourceOffset,
outputOffset,
outputBuffer,
channel;
if ((bufferLength % channels) !== 0) {
throw (new Error("Buffer was of incorrect sample length."));
}
if (bufferLength <= 0) {
return [];
}
outLength = this.outputBufferSize;
ratioWeight = this.ratioWeight;
weight = this.lastWeight;
firstWeight = 0;
secondWeight = 0;
sourceOffset = 0;
outputOffset = 0;
outputBuffer = this.outputBuffer;
for (; weight < 1; weight += ratioWeight) {
secondWeight = weight % 1;
firstWeight = 1 - secondWeight;
this.lastWeight = weight % 1;
for (channel = 0; channel < this.channels; ++channel) {
outputBuffer[outputOffset++] = (this.lastOutput[channel] * firstWeight) + (buffer[channel] * secondWeight);
}
}
weight -= 1;
for (bufferLength -= channels, sourceOffset = Math.floor(weight) * channels; outputOffset < outLength && sourceOffset < bufferLength;) {
secondWeight = weight % 1;
firstWeight = 1 - secondWeight;
for (channel = 0; channel < this.channels; ++channel) {
outputBuffer[outputOffset++] = (buffer[sourceOffset + ((channel > 0) ? (channel) : 0)] * firstWeight) + (buffer[sourceOffset + (channels + channel)] * secondWeight);
}
weight += ratioWeight;
sourceOffset = Math.floor(weight) * channels;
}
for (channel = 0; channel < channels; ++channel) {
this.lastOutput[channel] = buffer[sourceOffset++];
}
return this.bufferSlice(outputOffset);
};
}
multiTap() {
this.resampler = (buffer) => {
let bufferLength = buffer.length,
outLength,
output_variable_list,
channels = this.channels,
ratioWeight,
weight,
channel,
actualPosition,
amountToNext,
alreadyProcessedTail,
outputBuffer,
outputOffset,
currentPosition;
if ((bufferLength % channels) !== 0) {
throw (new Error("Buffer was of incorrect sample length."));
}
if (bufferLength <= 0) {
return [];
}
outLength = this.outputBufferSize;
output_variable_list = [];
ratioWeight = this.ratioWeight;
weight = 0;
actualPosition = 0;
amountToNext = 0;
alreadyProcessedTail = !this.tailExists;
this.tailExists = false;
outputBuffer = this.outputBuffer;
outputOffset = 0;
currentPosition = 0;
for (channel = 0; channel < channels; ++channel) {
output_variable_list[channel] = 0;
}
do {
if (alreadyProcessedTail) {
weight = ratioWeight;
for (channel = 0; channel < channels; ++channel) {
output_variable_list[channel] = 0;
}
} else {
weight = this.lastWeight;
for (channel = 0; channel < channels; ++channel) {
output_variable_list[channel] = this.lastOutput[channel];
}
alreadyProcessedTail = true;
}
while (weight > 0 && actualPosition < bufferLength) {
amountToNext = 1 + actualPosition - currentPosition;
if (weight >= amountToNext) {
for (channel = 0; channel < channels; ++channel) {
output_variable_list[channel] += buffer[actualPosition++] * amountToNext;
}
currentPosition = actualPosition;
weight -= amountToNext;
} else {
for (channel = 0; channel < channels; ++channel) {
output_variable_list[channel] += buffer[actualPosition + ((channel > 0) ? channel : 0)] * weight;
}
currentPosition += weight;
weight = 0;
break;
}
}
if (weight === 0) {
for (channel = 0; channel < channels; ++channel) {
outputBuffer[outputOffset++] = output_variable_list[channel] / ratioWeight;
}
} else {
this.lastWeight = weight;
for (channel = 0; channel < channels; ++channel) {
this.lastOutput[channel] = output_variable_list[channel];
}
this.tailExists = true;
break;
}
} while (actualPosition < bufferLength && outputOffset < outLength);
return this.bufferSlice(outputOffset);
};
}
resample(buffer) {
if (this.fromSampleRate == this.toSampleRate) {
this.ratioWeight = 1;
} else {
if (this.fromSampleRate < this.toSampleRate) {
this.lastWeight = 1;
} else {
this.tailExists = false;
this.lastWeight = 0;
}
this.initializeBuffers();
this.ratioWeight = this.fromSampleRate / this.toSampleRate;
}
return this.resampler(buffer)
}
}
registerProcessor("recorder.worklet", RecorderProcessor)

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"app_name":"extera_next","version":"2.0.0","package_name":"extera_next"}

Binary file not shown.

View File

@ -0,0 +1,11 @@
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 70.82 81.78">
<defs>
<linearGradient id="a" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="#406FBF" />
<stop offset="100%" stop-color="#23509D" />
</linearGradient>
</defs>
<path fill-rule="evenodd"
d="M70.82 44.98v16.36l-17.7 10.22-17.71 10.22-2.59-1.5L0 61.34V20.45l17.7-10.23L35.41 0l28.33 16.36 4.49 2.59 2.59 1.5v8.17L35.41 49.07l-7.08-4.09V36.8l21.25-12.27-14.17-8.17-21.25 12.26v24.54l21.25 12.26.03.02.02-.05z"
style="fill:url(#a)" />
</svg>

After

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

9
appimage/Extera.desktop Normal file
View File

@ -0,0 +1,9 @@
[Desktop Entry]
Type=Application
Version=1.0
Name=Extera Next
Comment=Matrix Client. Chat with your friends
Exec=AppRun
Icon=extera
Terminal=false
Categories=Network;Chat;InstantMessaging;X-Matrix;

View File

@ -2,6 +2,10 @@
"@@locale": "en",
"@@last_modified": "2025-06-05 12:38:37.885451",
"noSendPermission": "You can't send messages here",
"noMessagesYet": "No messages yet",
"longPressToRecordVoiceMessage": "Long press to record voice message.",
"pause": "Pause",
"resume": "Resume",
"@noSendPermission": {},
"alwaysUse24HourFormat": "false",
"@alwaysUse24HourFormat": {

View File

@ -3,6 +3,10 @@
"@@last_modified": "2021-08-14 12:41:09.903021",
"noSendPermission": "Вы не можете отправлять сообщения",
"@noSendPermission": {},
"noMessagesYet": "Нет сообщений",
"longPressToRecordVoiceMessage": "Зажмите, чтобы записать голосовое сообщение.",
"pause": "Пауза",
"resume": "Продолжить",
"alwaysUse24HourFormat": "нет",
"@alwaysUse24HourFormat": {
"description": "Set to true to always display time of day in 24 hour format."

View File

@ -40,7 +40,7 @@ abstract class FluffyThemes {
BuildContext context,
Brightness brightness, [
Color? seed,
bool? pureBlack,
bool? pureBlack,
]) {
final extraDarkColors = (brightness == Brightness.dark && pureBlack == true)
? {
@ -79,6 +79,7 @@ abstract class FluffyThemes {
useMaterial3: true,
brightness: brightness,
colorScheme: colorScheme,
useSystemColors: true,
dividerColor: brightness == Brightness.dark
? colorScheme.surfaceContainerHighest
: colorScheme.surfaceContainer,
@ -117,6 +118,8 @@ abstract class FluffyThemes {
isColumnMode ? colorScheme.surfaceContainer.withAlpha(128) : null,
surfaceTintColor: isColumnMode ? colorScheme.surface : null,
backgroundColor: isColumnMode ? colorScheme.surface : null,
actionsPadding:
isColumnMode ? const EdgeInsets.symmetric(horizontal: 16.0) : null,
systemOverlayStyle: SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: brightness.reversed,
@ -139,6 +142,7 @@ abstract class FluffyThemes {
),
snackBarTheme: isColumnMode
? const SnackBarThemeData(
showCloseIcon: true,
behavior: SnackBarBehavior.floating,
width: FluffyThemes.columnWidth * 1.5,
)

View File

@ -199,6 +199,30 @@ abstract class L10n {
/// **'You can\'t send messages here'**
String get noSendPermission;
/// No description provided for @noMessagesYet.
///
/// In en, this message translates to:
/// **'No messages yet'**
String get noMessagesYet;
/// No description provided for @longPressToRecordVoiceMessage.
///
/// In en, this message translates to:
/// **'Long press to record voice message.'**
String get longPressToRecordVoiceMessage;
/// No description provided for @pause.
///
/// In en, this message translates to:
/// **'Pause'**
String get pause;
/// No description provided for @resume.
///
/// In en, this message translates to:
/// **'Resume'**
String get resume;
/// Set to true to always display time of day in 24 hour format.
///
/// In en, this message translates to:

View File

@ -11,6 +11,19 @@ class L10nAr extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nBe extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nBn extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nBo extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nCa extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'true';

View File

@ -11,6 +11,19 @@ class L10nCs extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'Vypnuto';

View File

@ -11,6 +11,19 @@ class L10nDe extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'true';

View File

@ -11,6 +11,19 @@ class L10nEl extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nEn extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nEo extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nEs extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'falso';

View File

@ -11,6 +11,19 @@ class L10nEt extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nEu extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nFa extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nFi extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nFil extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nFr extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'true';

View File

@ -11,6 +11,19 @@ class L10nGa extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'bréagach';

View File

@ -11,6 +11,19 @@ class L10nGl extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'falso';

View File

@ -11,6 +11,19 @@ class L10nHe extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nHi extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nHr extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'true';

View File

@ -11,6 +11,19 @@ class L10nHu extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'true';

View File

@ -11,6 +11,19 @@ class L10nIa extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nId extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'tidak';

View File

@ -11,6 +11,19 @@ class L10nIe extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nIt extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'disattivato';

View File

@ -11,6 +11,19 @@ class L10nJa extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nKa extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nKo extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nLt extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nLv extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => '';

View File

@ -11,6 +11,19 @@ class L10nNb extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nNl extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'true';

View File

@ -11,6 +11,19 @@ class L10nPl extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nPt extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nRo extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nRu extends L10n {
@override
String get noSendPermission => 'Вы не можете отправлять сообщения';
@override
String get noMessagesYet => 'Нет сообщений';
@override
String get longPressToRecordVoiceMessage =>
'Зажмите, чтобы записать голосовое сообщение.';
@override
String get pause => 'Пауза';
@override
String get resume => 'Продолжить';
@override
String get alwaysUse24HourFormat => 'нет';

View File

@ -11,6 +11,19 @@ class L10nSk extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nSl extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nSr extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

View File

@ -11,6 +11,19 @@ class L10nSv extends L10n {
@override
String get noSendPermission => 'You can\'t send messages here';
@override
String get noMessagesYet => 'No messages yet';
@override
String get longPressToRecordVoiceMessage =>
'Long press to record voice message.';
@override
String get pause => 'Pause';
@override
String get resume => 'Resume';
@override
String get alwaysUse24HourFormat => 'false';

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