Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Support 32-bit Windows #1636

Closed
ghost opened this issue Nov 1, 2017 · 66 comments
Closed

[Feature Request] Support 32-bit Windows #1636

ghost opened this issue Nov 1, 2017 · 66 comments

Comments

@ghost
Copy link

ghost commented Nov 1, 2017

The desktop version for Windows only supports 64-bit Windows. Do you develop a version for 32-bit Windows in future?

@scottnonnenberg
Copy link
Contributor

To be honest, it's not very high on our list. We have more people asking for support for different distributions of Linux. Our research indicates that the vast majority of Windows users are on 64bit installs at this point.

Maybe you could tell me more about your situation? Find others in your situation?

@scottnonnenberg scottnonnenberg changed the title Will you support 32-bit Windows [Feature Request] Support 32-bit Windows Nov 16, 2017
@Dyras
Copy link

Dyras commented Nov 19, 2017

Backblaze claims only 4.3% of their Windows users run 32-bit versions of their software. Assuming it's the same for Signal, it doesn't seem worth bothering with it. As Scott said, I would prefer if they found a way of keeping their Flatpak up to date so that people won't be running ancient versions in a few months.

@Flexmaen
Copy link

Flexmaen commented Dec 3, 2017

I'm using 32bit Windows and wonder if it is really so much more work supporting 32bit Windows than some Linux distribution that has much less users.
4.3% of Windows users might still be more than most Linux distributions, regarding that OSX is coming second after Windows...

@Dyras
Copy link

Dyras commented Dec 3, 2017

You are absolutely right that there are fewer Linux users than 32-bit Windows users. However, I'd say there are more Signal Linux users than Signal 32-bit users since Linux users are usually more tech sawy and Signal has always been a nerd program. As Scott said, they are getting more requests for a Flatpak than they are for a 32-bit Windows version. Maybe they will consider making one for 32-bit users if the interest is high when the Flatpak is out, so who knows?

My last post here, don't want to spam Scott with emails. Feel free making a thread on the forum:
https://whispersystems.discoursehosting.net/

@solutionweb-ch
Copy link

I think you will lose less time developing a web-based solution like Whatsapp did, than developing 10 different OS versions.
I also run WIN 7 32 bits and I am annoyed.
Don't lose current Whatsapp/Facebook bad reputation benefits! It's time to...

@Jos512
Copy link

Jos512 commented May 8, 2018

Backblaze claims only 4.3% of their Windows users run 32-bit versions of their software. Assuming it's the same for Signal, it doesn't seem worth bothering with it.

Firefox's hardware report (source) says that 18% of FireFox users are still on 32-bit operating systems.

2018-05-08_21-07-59

There's a small decline in number of 32-bit users each quarter, but 18% is still a sizeable portion of computer users.

@nkrapivin
Copy link

I tried to install Signal in ReactOS. It didn't worked. Because ReactOS doesn't have 64-bit support.

@a-woolf
Copy link

a-woolf commented Sep 7, 2018

A 32-bit client would be 100% compatible with 64-bit Windows, and would be universal. On a tiny app like this are there even any benefits to being 64-bit only? Microsoft highly recommends using 32-bit Office (on 64-bit machines), unless spreadsheets are so large they run into memory constraints. Only then is 64-bit advised.

I use 32-bit clients whenever possible (VMs, etc) for speed and reduced memory footprint, and was utterly surprised when I found that Signal was 64-bit only.

As of May 2018, Firefox shows 30%+ of users are running 32-bit Firefox , and 18%+ of users are on a 32-bit OS. (Both metrics exclude XP/Vista.) This is a sizable chunk to write off completely.

@Trolldemorted
Copy link
Contributor

@a-woolf In general, you should avoid 32bit builds because 64bit has a plentitude of benefits, not limited to:

  • 8 additional general purpose registers
  • sse registers
  • nx bit for pages instead of segments
  • minor security benefits like a large address space which makes countermeasures like ASLR more effective

A more complete list is at wikipedia.

Signal-Desktop uses electron and thus is almost a full browser, not a small app. 32bit binaries would neither be faster (because they would use less registers and not cause significantly more cache misses), nor would the memory footprint increase by a noteworthy amount, since only pointers grow to the double of their size.

@Flexmaen
Copy link

But do we have any disadvantage? The 32bit client would run on any windows.
AFAIK Riot also uses electron and runs on 32bit Windows.

@Soldier4Life
Copy link

Soldier4Life commented Nov 13, 2018

I think you will lose less time developing a web-based solution like Whatsapp did, than developing 10 different OS versions.
I also run WIN 7 32 bits and I am annoyed.
Don't lose current Whatsapp/Facebook bad reputation benefits! It's time to...

I fully agree... kill a dozen birds with one stone. Go web-based as opposed to native apps. While most of my gear is x64, I do have a tiny Win10 32-bit tablet/hybrid I use for travel that I can no longer use Signal on. Major bummer. Web-based is definitely the way to go. I understand that there are security concerns with that... aka using a compromised or outdated browser... but that is the same for native apps... if the device is compromised or outdated, it poses increased risk. If you can't do web-based for some reason, at least do x86 for your main platform as mentioned above... then it will work on both x86 and x64 architectures.

@Flexmaen
Copy link

I fully agree... kill a dozen birds with one stone. Go web-based as opposed to native apps.

Nah... Web based things are slow and lack offline possibilities (in case you need to read something while disconnected). Telegram also has a native 32bit Windows app. Can't be too difficult if you can cross-compile the soure.

@andrejsky
Copy link

I'd like to mention a case where it's become impossible to run Signal on new(ish) hardware. Some laptops and tablets, even though the hardware is 64bit capable, have shipped with 32bit Windows 10 due to limited eMMC capacity of 32GB and perhaps other reasons. So it has become impossible to run Signal on these types of devices (prob. what also Soldier4Life above has experienced).

@Soldier4Life
Copy link

Soldier4Life commented Nov 17, 2018

I fully agree... kill a dozen birds with one stone. Go web-based as opposed to native apps.

Nah... Web based things are slow and lack offline possibilities (in case you need to read something while disconnected). Telegram also has a native 32bit Windows app. Can't be too difficult if you can cross-compile the soure.

I hear you... it is definitely a trade-off between broad spectrum compatibility and features/performance. It seems like the simple solution would be to just use x86 based architecture for all of Windows Desktop... then it can run on both. Unless there is a specific reason not to do so, that I might be missing.

@MagentaFocus
Copy link

I doubt I will be installing new copies of an operating system just to run an program that has been working for many years. At least let us use the old app and we can bear any security issues.

@openube
Copy link

openube commented Nov 30, 2018

I am incline to agree with MagentoUno, as long as the security issues are restricted merely to the 32bit machine, and not compromising the entire signal accounts on the contact list.

@psidre
Copy link

psidre commented Mar 16, 2019

I'm currently running Windows 7 32-bit and it's the only desktop PC I have. I use Signal on my phone because it has all the features I require.

I am sure I am not alone in the idea that most users do not care about the architecture of the software, but whether or not they can use it on all of their devices to stay connected.

If I had the skills, I would build a 32-bit release myself, but I do not.

It would be a lot to a lot of people to be able to have this option.

@gitoss
Copy link

gitoss commented Jun 8, 2019

I just wanted to install Signal on my thin laptop, too - tiny ssd, <4gb ram so it's running Win32 OS. Alas, no can do. Bye bye Signal, back to good ol' workin' Telegram. Meh.

@midtempo
Copy link

midtempo commented Nov 7, 2019

Listen, I am a nerd too. I own a Google Pixel 3a and will only buy phones whose bootloaders may be unlocked. My home computer runs Linux Mint.

However, I am at the mercy of my employer during weekdays. I have for years used Google Hangouts to message my wife because I can do so using the computer without having to alternate between my phone and my computer. As many of you know, Google Hangouts/Google Chat is a completely unsecured messaging system and the messages are infinitely stored on Google's servers for you to see. I would like to use Signal on my work Windows desktop computer, but it's running 32-bit Windows. This may not change for a few years when they replace the computer.

So I may be a nerd and have updated phones and a computer. But my workplace is another story. Please make it a priority to have a 32-bit Windows version. If there is already a 64-bit Windows version, is it much more work to port it to a 32-bit Windows version? Is this really an uncommon request?

If there is no 32-bit Windows version, I might want to switch to Whatsapp instead. Whatsapp is now owned by Facebook. I have never trusted Facebook and have not had a Facebook account for years.

@Flexmaen
Copy link

Flexmaen commented Nov 7, 2019

@midtempo you'd better switch to Riot.im if you want to stay with open source, this even has a federated server structure. Only downside is that you have to verify every device if you want to have encryption.

But back to Signal: Does a 32 bit version need a lot of rework, or does it just need someone who is able to compile a 32bit version without having to change a lot? In that case it would be great to have the possibility for donating for certain features.

@gitoss
Copy link

gitoss commented Nov 7, 2019

I've switched to Wire by now, it's evolving to a very mature oss client (https://github.com/wireapp/wire) and of course has a 32bit version (https://wire.com/en/download) ... I'd still like to use Signal for my legacy contacts, but as supporting a broad userbase isn't Signal's priority, supporting Signal isn't mine either.

@a-woolf
Copy link

a-woolf commented Jan 4, 2020

A 32-bit client would be 100% compatible with 64-bit Windows, and would be universal.

ARM64 Windows 10 can run Win32 (x86) apps, but cannot run Win64 (x86-64) apps without recompiling. This reinforces the need for a Win32 build - universal compatibility, as requested here over 2 years ago.

See: #3156 and #3745

@awnz
Copy link

awnz commented Mar 9, 2020

To add yet another use case, there's also a number of Intel Atom tablets out there (the 32-bit UEFI only ones, ie Clover Trail) which can only run 32-bit Windows 10. Some of us don't have the budget to replace these.

And the above line of "Signal has always been a nerd program" is the wrong approach, and a little bit self-defeating - if you want to get things like Signal into the hands of more people and not just journalists and nerds, you need to make it more widely compatible.

@erg
Copy link

erg commented Jun 4, 2020

Tech nerd here using a Microsoft Surface Pro X with an arm64 cpu that can run x86 apps but not x64. Both arm64 or x86 builds would work for me, but neither are supported.

VSCode just released arm64 support, here's their github issue: microsoft/vscode#33620

@a-woolf
Copy link

a-woolf commented Jun 4, 2020

Just build the dang 32 bit version already. People have been asking for it for years now.
More use cases keep coming up, as non-x86 systems can now run x86 code (but not x86-64 code).

@hoehermann
Copy link

hoehermann commented Jan 18, 2021

Hi there. Thanks for mentioning purple-signal. I am the author of purple-signal. I want to access signal without a resource-hogging browser solution. Long-term goal is a fully-fledged signal integration in Pidgin (with Pidgin 3 – if it ever gets released – probably supporting audio and video conferencing, too) and chatty. However, with libsignal-service-java being moved and hidden within the Signal-Android sources, libsignal-protocol-c looking abandoned and libsignal-client not deemed ready for production, I am trying to hit an elusive target which turns out to be moving rather swiftly. I will not supply users with the native binaries libsignal-service-java is depending on, especially if the number of dependencies increases. Right now with dennisameling, we are in luck, but that may change any time.

@Velox0
Copy link

Velox0 commented Feb 9, 2021

32 bit version when :(

@dennisameling
Copy link
Contributor

dennisameling commented Feb 12, 2021

Great news! I was able to get Signal to boot on Windows 10 32-bit (in a VM):

image

⚠️ This really only is a proof-of-concept for now!

We at least need the following PRs to be merged before the Signal team could even consider 32-bit builds:

For cross-reference: issue for Windows ARM64 support: #3745

I'm working from this branch: https://github.com/dennisameling/Signal-Desktop/tree/windows-multi-arch-support

✅ All automated tests are passing after applying the PRs above:

Test logs
PS C:\Users\Admin\repos\signal-desktop> yarn test
yarn run v1.22.10
$ yarn test-node && yarn test-electron
$ electron-mocha --file test/setup-test-node.js --recursive test/app test/modules ts/test-node ts/test-both

x-attr dependency did not load successfully

Attachments
createWriterForNew
√ should write file to disk and return path
createWriterForExisting
√ should write file to disk on given path and return path
√ throws if relative path goes higher than root
createReader
√ should read file from disk
√ throws if relative path goes higher than root
copyIntoAttachmentsDirectory
√ throws if passed a non-string
√ returns a function that rejects if the source path is not a string
√ returns a function that rejects if the source path is not in the user config directory
√ returns a function that copies the source path into the attachments directory
createDeleter
√ should delete file from disk
√ throws if relative path goes higher than root
createName
√ should return random file name with correct length
getRelativePath
√ should return correct path
createAbsolutePathGetter
√ combines root and relative path
√ throws if relative path goes higher than root

SignalMenu
createTemplate
macOS
without setup options
√ should return correct template
with setup options
√ should return correct template
Windows
without setup options
√ should return correct template
with setup options
√ should return correct template
Linux
without setup options
√ should return correct template
with setup options
√ should return correct template

Protocol Filter
_urlToPath
√ returns proper file path for unix style file URI with hash
√ returns proper file path for unix style file URI with querystring
√ returns proper file path for unix style file URI with hash and querystring
√ returns proper file path for file URI on windows
√ translates from URL format to filesystem format
√ translates from URL format to filesystem format
√ handles SMB share path
√ handles SMB share path on windows
√ hands back a path with .. in it

SpellCheck
getLanguages
√ works with locale and base available
√ works with neither locale nor base available
√ works with only base locale available
√ works with only full locale available
√ works with base provided and base available
√ works with base provided and base not available

Link previews
#isLinkSafeToPreview
√ returns false for invalid URLs
√ returns false for non-HTTPS URLs
√ returns false if the link is "sneaky"
√ returns true for "safe" urls
#findLinks
√ returns all links if no caretLocation is provided
√ includes all links if cursor is not in a link
√ excludes a link not at the end if the caret is inside of it
√ excludes a link not at the end if the caret is at its end
√ excludes a link at the end of the caret is inside of it
√ includes link at the end if cursor is at its end
#isLinkSneaky
√ returns true for =
√ returns true for $
√ returns true for +
√ returns true for ^
√ returns true for URLs with a length of 4097 or higher
auth
√ returns true for hrefs with auth (or pretend auth)
domain
√ returns false for all-latin domain
√ returns false for IPv4 addresses
√ returns true for IPv6 addresses
√ returns true for Latin + Cyrillic domain
√ returns true for Latin + Greek domain
√ returns true for ASCII and non-ASCII mix
√ returns true for Latin + High Greek domain
√ returns true if the domain doesn't contain a .
√ returns true if the domain has any empty labels
√ returns true if the domain is longer than 2048 UTF-16 code points
pathname
√ returns false for no pathname
√ returns false if the pathname contains valid characters
√ returns true if the pathname contains invalid characters
query string
√ returns false for no query
√ returns false if the query string contains valid characters
√ returns true if the query string contains invalid characters
hash
√ returns false for no hash
√ returns false if the hash contains valid characters
√ returns true if the hash contains invalid characters

Privacy
redactPhoneNumbers
√ should redact all phone numbers
redactUuids
√ should redact all uuids
redactGroupIds
√ should redact all group IDs
√ should remove newlines from redacted group IDs
√ should remove newlines from redacted group V2 IDs
redactAll
√ should redact all sensitive information
_redactPath
√ should redact file paths
√ should redact URL-encoded paths
√ should redact stack traces with both forward and backslashes
√ should redact stack traces with escaped backslashes

Attachment
replaceUnicodeOrderOverrides
√ should sanitize left-to-right order override character
√ should sanitize right-to-left order override character
√ should sanitize multiple override characters
√ should ignore non-order-override characters (112ms)
replaceUnicodeV2
√ should remove all bad characters
√ should should leave normal filename alone
√ should handle missing fileName
removeSchemaVersion
√ should remove existing schema version
migrateDataToFileSystem
√ should write data to disk and store relative path to it
√ should skip over (invalid) attachments without data
√ should throw error if data is not valid

Contact
parseAndWriteAvatar
√ handles message with no avatar in contact
√ turns phone numbers to e164 format
√ removes contact avatar if it has no sub-avatar
√ writes avatar to disk
√ removes number element if it ends up with no value
√ drops address if it has no real values
√ removes invalid elements if no values remain in contact
√ handles a contact with just organization
_validate
√ returns error if contact has no name.displayName or organization
√ logs if no values remain in contact

Errors
toLogFormat
√ should return error stack trace if present
√ should return error string representation if stack is missing
√ should return 0 argument
√ should return false argument
√ should return null argument
√ should return undefined argument

Message
createAttachmentDataWriter
√ should ignore messages that didn’t go through attachment migration
√ should ignore messages without attachments
√ should write attachments to file system on original path
√ should process quote attachment thumbnails
√ should process contact avatars
initializeSchemaVersion
√ should ignore messages with previously inherited schema
for message without attachments
√ should initialize schema version to zero
for message with attachments
√ should inherit existing attachment schema version
upgradeSchema
√ should upgrade an unversioned message to the latest version
with multiple upgrade steps
√ should return last valid message when any upgrade step fails
√ should skip out-of-order upgrade steps
_withSchemaVersion
√ should require a version number
√ should require an upgrade function
√ should skip upgrading if message has already been upgraded
√ should return original message if upgrade function throws
√ should return original message if upgrade function returns null
_mapQuotedAttachments
√ handles message with no quote
√ handles quote with no attachments
√ handles zero attachments
√ handles attachments with no thumbnail
√ does not eliminate thumbnails with missing data field
√ calls provided async function for each quoted attachment
_mapContact
√ handles message with no contact field
√ handles one contact

MIME
isJPEG
√ should return true for image/jpeg
√ should return false for jpg
√ should return false for jpeg
√ should return false for image/jpg
√ should return false for image/gif
√ should return false for image/tiff
√ should return false for application/json
√ should return false for 0
√ should return false for false
√ should return false for null
√ should return false for undefined

SchemaVersion
isValid
√ should return true for positive integers
√ should return false for any other value (40ms)

LeftPane
getRowFromIndex
given only pinned chats
√ returns pinned chats, not headers
given only non-pinned chats
√ returns conversations, not headers
given only pinned and non-pinned chats
√ returns headers and conversations
given not showing archive with archived conversation
√ returns an archive button last
given showing archive and archive chats
√ returns archived conversations

groupMediaItemsByDate
√ should group mediaItems

license comments
√ includes a license comment at the top of every relevant file (214ms)

isLinkPreviewDateValid
√ returns false for non-numbers
√ returns false for zero
√ returns false for NaN
√ returns false for any infinite value
√ returns false for timestamps more than a day from now
√ returns true for timestamps before tomorrow

uploadDebugLogs
√ makes a request to get the S3 bucket, then uploads it there
√ rejects if we can't get a token
√ rejects with an invalid token body
√ rejects if the upload doesn't return a 204

logging
#isLineAfterDate
√ returns false if falsy
√ returns false if invalid JSON
√ returns false if date is invalid
√ returns false if log time is invalid
√ returns false if date before provided date
√ returns true if date is after provided date
#eliminateOutOfDateFiles
√ deletes an empty file
√ deletes a file with invalid JSON lines
√ deletes a file with all dates before provided date
√ keeps a file with first line date before provided date
√ keeps a file with last line date before provided date
#eliminateOldEntries
√ eliminates all non-parsing entries
√ preserves all lines if before target date
#fetchLog
√ returns error if file does not exist
√ returns empty array if file has no valid JSON lines
√ returns just three fields in each returned line
#fetch
√ returns single entry if no files
√ returns sorted entries from all files

MemberRepository
#updateMembers
√ updates with given members
#getMemberById
√ returns undefined when there is no search id
√ returns a matched member
√ returns undefined when it does not have the member
#getMemberByUuid
√ returns undefined when there is no search uuid
√ returns a matched member
√ returns undefined when it does not have the member
#search
given a prefix-matching string on last name
√ returns the match
given a prefix-matching string on first name
√ returns the match
given a prefix-matching string on profile name
√ returns the match
given a prefix-matching string on title
√ returns the match
given a match in the middle of a name
√ returns zero matches

matchMention
√ handles an AtMentionify from clipboard
√ handles an MentionBlot from clipboard
√ converts a missing AtMentionify to string
√ converts a missing MentionBlot to string
√ passes other clipboard elements through

getDeltaToRemoveStaleMentions
given text
√ retains the text
given stale and valid mentions
√ retains the valid and replaces the stale
given emoji embeds
√ retains the embeds
given other ops
√ passes them through

getTextAndMentionsFromOps
given only text
√ returns only text trimmed
√ returns trimmed of trailing newlines
given text, emoji, and mentions
√ returns the trimmed text with placeholders and mentions
given only mentions
√ returns the trimmed text with placeholders and mentions
√ does not trim newlines padding mentions

getDeltaToRestartMention
given text and emoji
√ returns the correct retains, a delete, and an @

Attachment
getUploadSizeLimitKb
√ returns 6000 kilobytes for supported non-GIF images
√ returns 25000 kilobytes for GIFs
√ returns 100000 for other file types
getFileExtension
√ should return file extension from content type
√ should return file extension for QuickTime videos
getSuggestedFilename
for attachment with filename
√ should return existing filename if present
for attachment without filename
√ should generate a filename based on timestamp
for attachment with index
√ should generate a filename based on timestamp
isVisualMedia
√ should return true for images
√ should return true for videos
√ should return false for voice message attachment
√ should return false for other attachments
isFile
√ should return true for JSON
√ should return false for images
√ should return false for videos
√ should return false for voice message attachment
isVoiceMessage
√ should return true for voice message attachment
√ should return true for legacy Android voice message attachment
√ should return false for other attachments

Contact
getName
√ returns displayName if provided
√ returns organization if no displayName
√ returns givenName + familyName if no displayName or organization
√ returns just givenName
√ returns just familyName
contactSelector
√ eliminates avatar if it has had an attachment download error
√ does not calculate absolute path if avatar is pending
√ calculates absolute path

Message
initializeAttachmentMetadata
√ should classify visual media attachments
√ should classify file attachments
√ should classify voice message attachments
√ does not include long message attachments
√ handles not attachments

MIME
isGif
√ returns true for GIFs
√ returns false for non-GIFs

Settings
getAudioNotificationSupport
√ returns native support on macOS
√ returns no support on Windows 7
√ returns native support on Windows 8
√ returns custom support on Linux
isAudioNotificationSupported
√ returns true on macOS
√ returns false on Windows 7
√ returns true on Windows 8
√ returns true on Linux
isNotificationGroupingSupported
√ returns true on macOS
√ returns true on Windows 7
√ returns true on Windows 8
√ returns true on Linux
isHideMenuBarSupported
√ returns false on macOS
√ returns true on Windows 7
√ returns true on Windows 8
√ returns true on Linux
isDrawAttentionSupported
√ returns false on macOS
√ returns true on Windows 7
√ returns true on Windows 8
√ returns true on Linux

updater/signatures
#getVersion
√ successfully gets version
#getUpdateFileName
√ successfully gets version
#isUpdateFileNameValid
√ returns true for normal filenames
√ returns false for problematic names
#validatePath
√ succeeds for simple children
√ returns false for problematic names

updater/curve
√ roundtrips
√ verifies with our own key

updater/signatures
√ _getFileHash returns correct hash (54ms)
√ roundtrips binary file writes
√ roundtrips signature (90ms)
√ fails signature verification if version changes (90ms)
√ fails signature verification if signature tampered with (107ms)
√ fails signature verification if binary file tampered with (102ms)
√ fails signature verification if signed by different key (89ms)

combineNames
√ returns undefined if no names provided
√ returns first name only if family name not provided
√ returns returns combined names
√ returns given name first if names in Chinese
√ returns given name first if names in Japanese
√ returns given name first if names in Korean

getAnimatedPngDataIfExists
√ returns null for empty buffers
√ returns null for non-PNG files
√ returns null for non-animated PNG files
√ returns data for animated PNG files

getOwn
√ returns undefined when asking for a non-existent property
√ returns undefined when asking for a non-own property
√ returns own properties
√ works even if hasOwnProperty has been overridden for the object

getTextWithMentions
given mention replacements
√ replaces them
√ sorts them to go from back to front

getUserAgent
√ returns the right User-Agent on Windows
√ returns the right User-Agent on macOS
√ returns the right User-Agent on Linux
√ omits the platform on unsupported platforms

isFileDangerous
√ returns false for images
√ returns false for documents
√ returns true for executable files
√ returns true for Microsoft settings files
√ returns false for non-dangerous files that end in ".", which can happen on Windows
√ returns true for dangerous files that end in ".", which can happen on Windows
√ returns false for empty filename
√ returns false for exe at various parts of filename
√ returns true for upper-case EXE

isMuted
√ returns false if passed undefined
√ returns false if passed a date in the past
√ returns false if passed a date in the future

isPathInside
√ returns false if the child path is not inside the parent path
√ returns true if the child path is inside the parent path

LatestQueue
√ if the queue is empty, new tasks are started immediately
√ only enqueues the latest operation

nonRenderedRemoteParticipant
√ returns a video request object a width and height of 0

normalizeGroupCallTimestamp
√ returns undefined if passed NaN
√ returns undefined if passed 0
√ returns undefined if passed a negative number
√ returns undefined if passed a string that cannot be parsed as a number
√ returns undefined if passed a BigInt of 0
√ returns undefined if passed a negative BigInt
√ returns undefined if passed a non-parseable type
√ returns positive numbers passed in
√ parses strings as numbers
√ only parses the first 15 characters of a string
√ converts positive BigInts to numbers

sgnlHref
isSgnlHref
√ returns false for non-strings
√ returns false for invalid URLs
√ returns false if the protocol is not "sgnl:"
√ returns true if the protocol is "sgnl:"
√ accepts URL objects
isSignalHttpsLink
√ returns false for non-strings
√ returns false for invalid URLs
√ returns false if the protocol is not "https:"
√ returns true if the protocol is "https:"
√ returns false if username or password are set
√ returns false if port is set
√ accepts URL objects
parseSgnlHref
√ returns a null command for invalid URLs
√ parses the command for URLs with no arguments
√ parses a command's arguments
√ treats the port as part of the command
√ ignores duplicate query parameters
√ includes hash
√ ignores other parts of the URL
√ doesn't do anything fancy with arrays or objects in the query string
parseSignalHttpsLink
√ returns a null command for invalid URLs
√ handles signal.art links
√ handles signal.group links

sleep
√ returns a promise that resolves after the specified number of milliseconds

sniffImageMimeType
√ returns undefined for empty buffers
√ returns undefined for non-image files
√ sniffs ICO files
√ sniffs BMP files
√ sniffs GIF files
√ sniffs WEBP files
√ sniffs PNG files
√ sniffs JPEG files
√ handles ArrayBuffers

sortByTitle
√ does nothing to arrays that don't need to be sorted
√ sorts the array by title
√ doesn't mutate its argument

toggleMaximizedBrowserWindow
√ maximizes an unmaximized window
√ unmaximizes a maximized window

writeWindowsZoneIdentifier
√ writes zone transfer ID 3 (internet) to the Zone.Identifier file
√ fails if there is an existing Zone.Identifier file
√ fails if the original file does not exist
√ fails if not on Windows

environment utilities
parseEnvironment
√ returns Environment.Production for non-strings
√ returns Environment.Production for invalid strings
√ parses "development" as Environment.Development
√ parses "production" as Environment.Production
√ parses "staging" as Environment.Staging
√ parses "test" as Environment.Test
√ parses "test-lib" as Environment.TestLib

shouldUseFullSizeLinkPreviewImage
√ returns false if there is no image
√ returns false is the preview is a sticker pack
√ returns false if either of the image's dimensions are missing
√ returns false if either of the image's dimensions are <200px
√ returns false if the image is square
√ returns false if the image is roughly square
√ returns false for large attachments that aren't images
√ returns true for larger images

cleanDataForIpc
√ does nothing to JSON primitives
√ does nothing to undefined
√ converts BigInts to strings
√ converts functions to undefined but does not mark them as cleaned, for backwards compatibility
√ converts symbols to undefined
√ converts ArrayBuffers to undefined
√ converts valid dates to ISO strings
√ converts invalid dates to undefined
√ converts other iterables to arrays
√ deeply cleans arrays, removing undefined and nulls
√ deeply cleans sets and converts them to arrays
√ deeply cleans maps and converts them to objects
√ calls toNumber when available
√ deeply cleans objects with a null prototype
√ deeply cleans objects with a prototype of Object.prototype
√ deeply cleans class instances

both/state/selectors/conversations
#getConversationSelector
√ returns empty placeholder if falsey id provided
√ returns empty placeholder if no match
√ returns conversation by e164 first
√ returns conversation by uuid
√ returns conversation by groupId
√ returns conversation by conversationId
√ does proper caching of result
#getLeftPaneList
√ sorts conversations based on timestamp then by intl-friendly title
given pinned conversations
√ sorts pinned conversations based on order in storage

both/state/selectors/items
#getPinnedConversationIds
√ returns pinnedConversationIds key from items
√ returns empty array if no saved data

both/state/selectors/search
#getMessageSearchResultSelector
√ returns undefined if message not found in lookup
√ returns undefined if type is unexpected
√ returns incoming message
√ returns outgoing message and caches appropriately

assert
√ does nothing if the assertion passes
√ throws because we're in a test environment

assignWithNoUnnecessaryAllocation
√ returns the same object if there are no modifications
√ returns a new object if there are modifications
√ only performs a shallow comparison
√ doesn't modify the original object when there are no modifications
√ doesn't modify the original object when there are modifications

calling notification helpers
getCallingNotificationText
√ says that the call has ended
√ includes the creator's first name when describing a call
√ if the creator doesn't have a first name, falls back to their title
√ has a special message if you were the one to start the call
√ handles an unknown creator

isIterable
√ returns false for non-iterables
√ returns true for iterables

makeLookup
√ returns an empty object if passed an empty array
√ returns an object that lets you look up objects by string key
√ if there are duplicates, the last one wins
√ ignores undefined properties
√ allows key of 0
√ converts the lookup to a string
√ looks up own and inherited properties

reallyJsonStringify
√ returns the same thing as JSON.stringify when JSON.stringify returns a string
√ returns a string when JSON.stringify returns undefined
√ returns a string when JSON.stringify would error

themeClassName
√ returns "light-theme" when passed a light theme
√ returns "dark-theme" when passed a dark theme

version utilities
isBeta
√ returns false for non-beta version strings
√ returns true for beta version strings

both/util/webSafeBase64
√ roundtrips with all elements
#toWebSafeBase64
√ replaces +
√ replaces /
√ removes =
#fromWebSafeBase64
√ replaces -
√ replaces _
√ adds ===
√ adds ==
√ adds =

449 passing (2s)

$ yarn grunt test
$ grunt test
Running "unit-tests" task
Starting path C:\Users\Admin\repos\signal-desktop\node_modules.bin\electron.cmd with args [ 'C:\Users\Admin\repos\signal-desktop\main.js' ]
App started. Now waiting for test results...

459 tests passed.

Running "lib-unit-tests" task
Starting path C:\Users\Admin\repos\signal-desktop\node_modules.bin\electron.cmd with args [ 'C:\Users\Admin\repos\signal-desktop\main.js' ]
App started. Now waiting for test results...

123 tests passed.

Done.
Done in 23.69s.

@hoehermann
Copy link

I welcome dennisameling's win32 builds of zkgroup.dll very much. The node binary seems to be okay for node usage, but does anyone know any sources for a win32 build of signal_jni.dll for native use? My users request it, but I do not really want to build it myself.

@mailinglists35
Copy link

@scottnonnenberg-signal looks like some volunteers are making progress on building signal 32 bit for windows and judging by the number of comments and participants this is not really an insignificant number of 32 bit users.

is there any plan to change this in your priority list and start working with @dennisameling to bring this into official release? there are lots of older hardware in the less developed areas that runs 32bit windows because there is no justification for a more resource hungry 64bit build on the same hardware.

a 2010 HP desktop that originally was shipped with windows xp, now runs windows 10 LTSC 32bit (receives security updates until 2029!!!) very well, but cannot use 64bit apps. except for exposing hypervisor features into a kvm guest and passing through a pci domain into a kvm guest, I've never needed 64bits on a desktop machine. all 32bit variants of the browsers run faster than their 64bit parts without missing any web features.

I understand you devs look forward into the future and the future is 64bit, but ask yourself, is this actually worth it? is it worth to leave the less developed areas/contries into the dark just because they can't afford hardware to run 64bit at decent speed?

@mailinglists35
Copy link

mailinglists35 commented Apr 26, 2021

To earlier comments in the thread, some of us are "nerds" enough that we're trying to bring our Boomer parents into the 20th century. I doubt mine are running anything above Windows XP right now, but I really want to be able to use a secure video client with them when we talk. They don't even understand what 32bit or 64bit IS and we're 3000 miles apart, doing tech support over chat - Signal of all things. And they can't figure out why it won't install.

please, get rid of that xp. it was the absolute best windows microsoft ever made but now it is a big risk of getting ransomware. if your cpu platform is Wolfdale or newer, windows 10 ltsc 32bit runs fine and you get security updates until 2029. it can do video calling and social media without problems. it's quite a pain to upgrade (xp -> vista -> 7 -> 7 enterprise -> 10 ltsb 2015 -> 10 ltsc 2019) so consider a fresh install instead on next visit.

move the OS to a SSD, add some ram if you have free dimm sockets, setup automatic updates, install an antivirus and you get a fast and automatic secure solution for your folks that doesn't need intensive maintenance until 2029!

@dennisameling
Copy link
Contributor

Here's a production build of Signal Desktop 5.2.0 arm64+ia32 (32-bit): https://github.com/dennisameling/Signal-Desktop/releases/tag/v5.2.0

I plan to update the production builds regularly until the Signal team does, but it also means that auto-updating is disabled for now. You can either subscribe to this issue or my fork to be notified when a new version becomes available 😊

@MagentaFocus
Copy link

MagentaFocus commented May 27, 2021 via email

@Septa9
Copy link

Septa9 commented May 28, 2021

Yesterday evening I installed the 32 bit Signal Desktop on the most underpowered notebook I could find (Atom N570, 2 GB, Win 10). Et voilà, it worked! At one point it failed to open the settings dialog (showing a blue rectangle instead) and had to be stopped via Task Manager, but that may be due to the sparse hardware resources.

Many thanks, Dennis, for the excellent work!

@dennisameling
Copy link
Contributor

@MagentaFocus thanks for the kind words and for the sponsorship! Really appreciate that! 😊

Thanks for testing @Septa9, I just tried in my 32-bit Windows 10 VM and was able to open the settings dialog there. But the VM has 4GB RAM available 😊 Do let me know if you come across any other problems!

If you haven't seen it yet, you can now also download v5.3.0: https://github.com/dennisameling/Signal-Desktop/releases/tag/v5.3.0-multi-arch

@dennisameling
Copy link
Contributor

Some very exciting news - just released 5.4.0 with a bunch of optimizations! Auto-updates are enabled now through my custom server. So, you should automatically be notified when 5.5.0 becomes available at some point. Next to that, the app has been fully signed with a Code Signing Certificate, so over time you most likely won't get warnings from Windows Defender SmartScreen anymore 👍🏼

Large parts of the build process are now automated, but there's still quite some moving parts that I'd like to automate even more. Will work on that in the coming weeks, though with low prio now that we have a stable foundation.

Do let me know if this release works for you - can't wait for you to see the auto-update mechanism in action when the next version comes out! Tested it locally and it works great 🎉

image

@MagentaFocus
Copy link

MagentaFocus commented Jun 6, 2021 via email

@dennisameling
Copy link
Contributor

5.4.1 is out! https://github.com/dennisameling/Signal-Desktop/releases/tag/v5.4.1-multi-arch

Users who are already on 5.4.0 will get an in-app notification that an update is ready 🚀

@Septa9
Copy link

Septa9 commented Jun 9, 2021

Hi Dennis,

There was a small inconvenience when manually installing 5.4.0, but this probably had to be expected: I had to re-link the phone, thereby losing all the chats already stored in desktop Signal. However, your auto-update to 5.4.1 worked like a charm, Congratulations!

@dennisameling
Copy link
Contributor

@Septa9 Yes, that's expected indeed, since I use a different App ID now for Signal Unofficial, to not cause conflicts with the official Signal client. I think you can copy over the contents of %APPDATA%\Signal to %APPDATA%\Signal Unofficial (some folks did this on macOS and it worked), though I'm not 100% sure if that'll also work on Windows. At least it's a one-time thing to do 😊

@Septa9
Copy link

Septa9 commented Jun 9, 2021

copy over the contents of %APPDATA%\Signal to %APPDATA%\Signal Unofficial

Not worth the effort. I just reported this for the sake of completeness.

@dennisameling
Copy link
Contributor

@Septa9
Copy link

Septa9 commented Jun 18, 2021

5.5.0 now live: https://github.com/dennisameling/Signal-Desktop/releases/tag/v5.5.0-multi-arch

...installed automatically, no issues so far.

@dennisameling
Copy link
Contributor

This is an automated message that version 5.7.1 is now live. Please note that it might take 1-2 hours for the binaries to be uploaded to the server.

Release URL: https://github.com/dennisameling/Signal-Desktop/releases/tag/v5.7.1-multi-arch

@dennisameling
Copy link
Contributor

This is an automated message that version 5.8.0 is now live. Please note that it might take 1-2 hours for the binaries to be uploaded to the server.

Release URL: https://github.com/dennisameling/Signal-Desktop/releases/tag/v5.8.0-multi-arch

@dennisameling
Copy link
Contributor

Just wanted to inform folks here that I'll have to stop supporting Signal 32-bit.

Over the last few months, my main focus was to get Signal to work on Apple Silicon and Windows arm64. The main chunk of that work was to get their native dependencies like ringrtc and signal-client to build for other architectures than x64, which was the only architecture the Signal team supported back then.

Though the Signal team merged my work on cross-compilation into their native dependencies, they were still only providing official x64 prebuilds for ringrtc and signal-client. It did mean, however, that I could start providing consistent prebuilds for non-x64 architectures like ia32 and arm64 by simply building them myself.

For every single update the Signal team did to their native dependencies, I had to trigger a build of those for ia32, x64 and arm64, and update the commit ref in my fork to point to these prebuilds. Luckily GitHub Actions helped me a lot to automate large parts of that process (building ringrtc takes 1+ hour!), but it did require me to spend some time every release to kick off that process and incorporate it into my fork. That's between 30-40 times since May/June 2021! Not every Signal Desktop update included updates to its native dependencies, but many of them did.

This is changing now. The Signal team introduced official Apple Silicon support in version 5.27.1, meaning they also started providing prebuilds for ringrtc and signal-client for Apple Silicon. They will also be providing official Windows + Linux arm64 versions of their ringrtc and signal-client native dependencies moving forward. This means that I don't need to build those native dependencies any longer for those platforms, meaning ~75% less of a maintenance burden!

However, those official prebuilds are not available for 32-bit platforms. Next to that, usage of ia32/32-bit Windows is still steadily declining (market share of 0.4% at the time of writing), and Windows 11 is not even available for 32-bit systems.

For the two reasons above, I can't justify the significant maintenance burden anymore of building the native dependencies just for ia32/32-bit, let alone testing whether Signal runs properly on that platform.

If someone wants to take this on, I'm more than happy to explain how you can do it (including code signing, setting up your own update infrastructure, etc.), but I'll stop providing "my" builds for ia32/32-bit soon. I'll keep doing it for the coming two minor versions (5.34.0 and 5.35.0), but those will be the final releases.

Thanks everyone for the great enthusiasm and support, really appreciate it! Again, if you are or know anyone who can and wants to take this on, it is certainly possible. I'll just be spending my energy on other open source work moving forward. 🙏🏼

@Septa9
Copy link

Septa9 commented Feb 28, 2022

Hi Dennis,

it's a pity that you have so stop supporting Win32 signal, but I understand your reasons. Thanks a lot for all the work you've done in the past!

@rsilvers129
Copy link

Of course I normally run Signal on my 64 bit machines, but my CNC controller for Mach3 needs 32 bit Windows. It would be nice to have Signal on it so that I don't have to use my phone when I am in front of it.

@janot
Copy link

janot commented Sep 10, 2022

@dennisameling maybe you could find time to publish guide on building Signal for 32bit Windows?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests