something

This commit is contained in:
OfficialDakari 2025-10-02 11:59:33 +05:00
parent b4fa4a7208
commit bffde24279
56 changed files with 3389 additions and 30 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

@ -405,18 +405,18 @@ packages:
dependency: "direct main"
description:
name: file_picker
sha256: "13ba4e627ef24503a465d1d61b32596ce10eb6b8903678d362a528f9939b4aa8"
sha256: f2d9f173c2c14635cc0e9b14c143c49ef30b4934e8d1d274d6206fcb0086a06f
url: "https://pub.dev"
source: hosted
version: "10.2.1"
version: "10.3.3"
file_selector:
dependency: "direct main"
description:
name: file_selector
sha256: "5019692b593455127794d5718304ff1ae15447dea286cdda9f0db2a796a1b828"
sha256: "5f1d15a7f17115038f433d1b0ea57513cc9e29a9d5338d166cb0bef3fa90a7a0"
url: "https://pub.dev"
source: hosted
version: "1.0.3"
version: "1.0.4"
file_selector_android:
dependency: transitive
description:
@ -957,66 +957,66 @@ packages:
dependency: "direct main"
description:
name: image_picker
sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a"
sha256: "736eb56a911cf24d1859315ad09ddec0b66104bc41a7f8c5b96b4e2620cf5041"
url: "https://pub.dev"
source: hosted
version: "1.1.2"
version: "1.2.0"
image_picker_android:
dependency: transitive
description:
name: image_picker_android
sha256: "317a5d961cec5b34e777b9252393f2afbd23084aa6e60fcf601dcf6341b9ebeb"
sha256: "8dfe08ea7fcf7467dbaf6889e72eebd5e0d6711caae201fdac780eb45232cd02"
url: "https://pub.dev"
source: hosted
version: "0.8.12+23"
version: "0.8.13+3"
image_picker_for_web:
dependency: transitive
description:
name: image_picker_for_web
sha256: "717eb042ab08c40767684327be06a5d8dbb341fe791d514e4b92c7bbe1b7bb83"
sha256: "40c2a6a0da15556dc0f8e38a3246064a971a9f512386c3339b89f76db87269b6"
url: "https://pub.dev"
source: hosted
version: "3.0.6"
version: "3.1.0"
image_picker_ios:
dependency: transitive
description:
name: image_picker_ios
sha256: "05da758e67bc7839e886b3959848aa6b44ff123ab4b28f67891008afe8ef9100"
sha256: eb06fe30bab4c4497bad449b66448f50edcc695f1c59408e78aa3a8059eb8f0e
url: "https://pub.dev"
source: hosted
version: "0.8.12+2"
version: "0.8.13"
image_picker_linux:
dependency: transitive
description:
name: image_picker_linux
sha256: "34a65f6740df08bbbeb0a1abd8e6d32107941fd4868f67a507b25601651022c9"
sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4"
url: "https://pub.dev"
source: hosted
version: "0.2.1+2"
version: "0.2.2"
image_picker_macos:
dependency: transitive
description:
name: image_picker_macos
sha256: "1b90ebbd9dcf98fb6c1d01427e49a55bd96b5d67b8c67cf955d60a5de74207c1"
sha256: d58cd9d67793d52beefd6585b12050af0a7663c0c2a6ece0fb110a35d6955e04
url: "https://pub.dev"
source: hosted
version: "0.2.1+2"
version: "0.2.2"
image_picker_platform_interface:
dependency: transitive
description:
name: image_picker_platform_interface
sha256: "886d57f0be73c4b140004e78b9f28a8914a09e50c2d816bdd0520051a71236a0"
sha256: "9f143b0dba3e459553209e20cc425c9801af48e6dfa4f01a0fcf927be3f41665"
url: "https://pub.dev"
source: hosted
version: "2.10.1"
version: "2.11.0"
image_picker_windows:
dependency: transitive
description:
name: image_picker_windows
sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb"
sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae
url: "https://pub.dev"
source: hosted
version: "0.2.1+1"
version: "0.2.2"
import_sorter:
dependency: "direct dev"
description:
@ -2373,5 +2373,5 @@ packages:
source: hosted
version: "3.1.3"
sdks:
dart: ">=3.8.0 <4.0.0"
flutter: ">=3.29.0"
dart: ">=3.9.0 <4.0.0"
flutter: ">=3.35.0"

View File

@ -26,8 +26,8 @@ dependencies:
emoji_picker_flutter: ^3.1.0
emojis: ^0.9.9
#fcm_shared_isolate: ^0.2.0
file_picker: ^10.2.1
file_selector: ^1.0.3
file_picker: ^10.3.3
file_selector: ^1.0.4
flutter:
sdk: flutter
flutter_cache_manager: ^3.4.1
@ -58,7 +58,7 @@ dependencies:
html: ^0.15.4
http: ^1.2.0
image: ^4.1.7
image_picker: ^1.1.0
image_picker: ^1.2.0
intl: ^0.20.2
just_audio: ^0.9.39
latlong2: ^0.9.1
@ -104,7 +104,7 @@ dependencies:
dev_dependencies:
flutter_lints: ^3.0.0
flutter_native_splash: ^2.0.3+1
flutter_native_splash: ^2.4.6
flutter_test:
sdk: flutter
import_sorter: ^4.6.0