messagekit / messagekit Goto Github PK
View Code? Open in Web Editor NEWA community-driven replacement for JSQMessagesViewController
Home Page: https://messagekit.github.io
License: MIT License
A community-driven replacement for JSQMessagesViewController
Home Page: https://messagekit.github.io
License: MIT License
๐
The cells should be laid out starting from the bottom and additional cells should be added to the top of the previous cell. This will allow the user to paginate upwards to new messages.
Some discussion around this topic can be found here: #12
I guess this is ultimately about pagination. I never really thought of handling it in this library ๐ค
The sample app crashes when you sent empty message list.
I debugged into the code and found the issue in MessagesCollectionView.swift.
var indexPathForLastItem: IndexPath? {
let lastSection = numberOfSections > 0 ? numberOfSections - 1 : 0
guard numberOfItems(inSection: lastSection) > 0 else { return nil }
return IndexPath(item: numberOfItems(inSection: lastSection) - 1, section: lastSection)
}
if numberOfSections is 0, the lastSection should not exist and return nil, but here retrieving section 0.
Hi, @SD10:
Great job! ๐
Here is a suggestion on detail. How about scrolling Collection View to latest message while showing keyboard? The following is comparison on this between MessageKit and JSQMessagesViewController.
Thanks
I'd like some images for the message bubbles, it could be an easy contribution ๐
Requirements
iMessage Bubbles
Google Hangout Bubbles
(looks like hangouts has a more subtle corner radius)
These bubble styles are still undetermined because I'm unsure of the style and how message grouping.
WhatsApp Bubbles
Kik Messenger Bubbles
Users should be able to adjust the inset from the end of the messageContainerView
to the edge of the Cell
.
Should be as simple as adding another property to MessagesCollectionViewLayout
and taking it into account when calculating the frame sizes.
Hey Everyone,
We have a slack channel secured for helping coordinating features and dev in real time. Most conversations/discussions will happen here on github and we want to keep it that way. But at times tho it can be difficult to get things merged in when there are conflicts so we have created this slack group.
Click the link to join. Be respectful and encouraging.
This link will expire a week from 9/7/2017 please message me if it past that time and you would like to join.
Hi,
So when keyboard showing we can scroll collection view with method scrollToBottom but i think it's not good solution because if we are positioning on the middle of chat history and expand keyboard it will scroll to end of the chat history. So WhatsApp/Viber has some different solution to move entire view up when keyboard showing on the screen. What do you think about it, for me it sounds good.
I'd like to create a custom UIView
subclass, MessageContainerView
, that takes in a MessageStyle
argument which is represented as an enum
.
enum MessageStyle {
case bubble(cornerRadius: CGFloat)
case bubbleTailed(cornerRadius: CGFloat)
case bubbleOutline(cornerRadius: CGFloat)
case custom(UIView)
case none
}
Then have a delegate method:
func styleForMessage(_ message: MessageType, at indexPath: IndexPath, in collectionView: MessagesCollectionView) -> MessageStyle
This is a really rudimentary and rough around the edges. But seems like a cool idea and user friendly.
It would be nice to be able to move the AvatarView around the cell.
I'm thinking we could allow it to be in 3 positions:
enum AvatarPosition {
case top
case messageCenter
case bottom
}
This could play well with MessageContainerView
customizations. Such as allowing the users to set which edge of the MessageContainerView
has a tail and adjusting the avatar accordingly.
I have noticed a small issue with the messagesCollectionView
top constraint, which is not with its superviewโs top but on topLayoutGuide
. I believe it was made this way to avoid problems between autoInset
of the scroll view and the inset manually changed when showing / hidding the keyboard.
I think the messagesCollectionViewโs top layout constraint should be with the top of its superview anyways to get advantage of the navigation barโs transparency (as iMessage app does)
Hey everyone ๐ ,
After 4 long years of hard work and dedication, Jesse Squires recently deprecated one of the most widely used open source iOS projects - JSQMessagesViewController. I believe this project's popularity is evidence enough that the iOS community should continue moving it forward.
The current state of JSQMessageViewController is rock solid. It's been reiterated, battled tested over 4 years, and used by countless apps in production.
It's safe to say that JSQMessagesViewController will continue to serve the needs of developers for a great time to come, but before the day comes where this is no longer the case -- I propose we have a plan for moving forward.
MessageKit
.I think these two points are important to building an inclusive community where every contributor feels a sense of ownership, importance, and welcome.
While there's nothing wrong with Obj-C, I think this is a good opportunity to consider the future of iOS development and port the project to Swift. I believe a Swift codebase will encourage a greater number of contributors and bring fresh blood to the project.
Open source projects require an enormous amount of effort to maintain. Instead of building competing MessagesViewController, we should all come together to deliver the highest quality project we can on behalf of the iOS community.
I remember at the old MessageKit repo there were countless comments from people willing to contribute.
I encourage everyone to share their thoughts and suggestions for the future of this project.
Please discuss any issues/ideas/concerns below.
I'll put together a Vision.md but for now here are some basic thoughts for v1.
Please use bullet points to make things easier to digest
The README could use some work ๐
.
I'll definitely work on updating it but this is also a good starter task.
We also could use a banner for the README.
Something like the JSQMessagesViewController banner would be great.
I'm open to other designs, I'm just not a good artist so I have no suggestions.
Overall, I'd like to continue using the current MessageKit logo.
This project began in part because of the deprecation of JSQMessagesViewController, but that does not mean it is simply JSQMessagesViewController rewritten in Swift. While there is some degree of expected migration to this project from JSQ, it is not about making a drop-in 1:1 replacement. While a lot of healthy architecture discussion has already been happening, we are also already seeing predictable confusion bubbling to the surface. It is going to be very repetitive having the same discussions over and over if we don't settle this very early on.
โGrowth is painful. Change is painful. But nothing is as painful as staying stuck somewhere you don't belong.โ - Mandy Hale
So far a core philosophical difference in the future of this project has arisen due to this overt relationship with JSQMessagesViewController: Are we devoted to Swift and the innovative future it offers with increasing developer support, or are we making legacy-code support a primary goal by requiring Objective-C compatible interfaces and APIs?
We cannot satisfy both without such things as: making sacrifices in the long-term design, architecture, and optimizations; adding complexity to the style guidelines for contributions; and allowing the continuation of an endless stream of debates regarding Objective-C vs Swift legacy support.
So far this project has already started to adopt components of JSQ's likeness and even a part of its following. I think while it is very healthy to use the past project's successes as inspirational guidelines for what is right and should be carried forward, it is equally unhealthy to let the past dictate the progress to be made by letting is hover over everything like a superficial target to live up to. If people want JSQMessagesViewController they already have that option or one of its numerous forks. We don't need to rehash every issue, debate, discussion, or decision that was made with regards to JSQMessagesViewController in the context of legacy support or its compliance with Objective-C specific implementations.
What I propose is that we make a clear distinction going forward: either we are inextricably linked to JSQ's APIs and legacy support requirements in some form - thereby embracing the confusion already created, or we are an independent project without any explicit requirements tied to past implementations or architectures of other libraries other than Apple's own.
If we are going to make the distinction clear, that means making at least a few decisions right off the bat:
No reuse of things like the JSQMessagesViewController logo on the organization or project. We should have a distinct look and feel that represents this project not a rehash of the past. Even if the change is simply the choice of color on the logo, it is better than keeping it as-is. Reusing the same logo unaltered is bound to further embroil us in confusion as to the overall expectations and direction of this project.
Rephrasing the organization's description from "In-progress: A community-driven replacement for JSQMessagesViewController" to something which directly addresses the overall focus of the project, not just one of its inspirations. That means something like "A community-driven messages UI library for Swift."
Style guideline inclusion limiting any use of the JSQ prefix anywhere in the MessageKit library. If any prefix is to be used, it should be MK.
Any documentation that was used in JSQMessagesViewController should not be reused word for word to prevent search engines from adding additional confusion.
JSQ API formats should be treated explicitly as guidelines not absolutes. That means, we should not be arbitrarily scoping development to require compliance with any of the past project's decisions. This is essentially about making it clear that we are not solely focused on keeping external API continuity while reworking internals. This is a ground-up refresh of everything to deal with the changing requirements of the next 4-5 years, not a perfection of what the requirements were in the past. JSQMessagesViewController supports iOS 7.0 and above, but we should not be expecting or considering anywhere near that same level of compatibility with older versions of iOS. As such, no breaking change should be off the table due to legacy support or anything regarding versions of iOS prior to 9.x or 10.x. If people want to target those older versions, they already have options. We do not need to be another.
A new re-written accessory view to be used to create robust and customizable MessageInputBar's
It's been a real challenge trying to size the MessageCollectionViewCell
's for messages that use NSAttributedString
's for their text. Actually, sizing anything using NSAttributedString
s.
NSAttributedString has a method:
boundingRect(size:options:context:)
It's been pretty useless so far. It doesn't come close to returning a correct for Strings greater than a single line. Often returning sizes off by 200% - 400%. I'm assuming it only gets more inconsistent as the size of the String grows. Too bad this method is declared as an extension of NSAttributeString
inside of UIKit and not part of swift-corelibs-foundation -- so I can't even view the implementation.
Currently, I added a UILabel
to the MessagesCollectionViewLayout
object which we use to calculate the bounding rect for a NSAttributedString
.
Personally, I'm not happy with this solution -- it's clearly a hack and I'm not sure what negative implications it would have on the library or performance. But for now, it's getting the job done.
You could argue that using this method, we could just switch to using a UITextView
inside of the MessageCollectionViewCell
and use this same approach. I'm going to refrain from doing so -- in hopes that this is a temporary solution.
Messages using regular String's as the text are unaffected. I still calculate the bounding rect manually.
Essentially, what we need is the implementation of UIView
's method sizeThatFits(size:)
without the overhead of a UI element. I've tried dropping down to CoreText and making my own calculations but it has yet to yield any results.
I'll have to review TTTAttributedLabel
to see if they have some sort of sizing code that doesn't rely on UIKit internals.
Anyone with experience with this topic feel free to pitch in ๐ All I see is a ton of unanswered Stack Overflow questions regarding the inconsistencies.
@jessesquires Any advice? ๐
Increasing test coverage is always an easy way to get involved in the project. I plan on focusing on this in upcoming releases but always open to help ๐ค
Not trying to start a holywar! Just want to make sure we don't have a lot of thrash with new contributions matching each developer's personal settings.
I think we need a maintenance-only "LTS" version of JSQMessagesViewController here: https://github.com/MessageKit/JSQMessagesViewController
The current repository in the MessageKit org is a fork of the original, but I believe @jessesquires should move ownership of the original upstream repo to this organization, and grant some of us the ability to push hotfix releases to CocoaPods.
There are some significant UI issues with JSQMessagesViewController in iOS 11, which means there are 40,000+ apps that will suddenly become broken without a clear path forward. I understand Jesse's reasons for deprecating the project, but I think the community needs to be given a chance to maintain the original code while the "next generation" replacement is stabilizing.
I'd like to step forward as a maintainer of the legacy code. I'm the primary maintainer of a number of other popular open source libraries like CocoaAsyncSocket, XMPPFramework, and KissXML. My goal as a maintainer would be to merge critical bug fixes only, and maintain clear warnings that the project is deprecated.
If we work together we can make this transition a lot easier for everyone.
My thoughts for an initial MessageKit roadmap.
This is not set in stone and open for discussion:
Please comment below ๐
attributedText(NSAttributedString)
for MessageLabel
cellTopLabel
/ cellBottomLabel
MessageLabel
MessageTopCell
and MessageBottomCell
MessagesCollectionView
MessagesViewController
that doesn't require any MessageKit protocolsI have created a group message-kit
in slack to help us be organized.
I would love to keep this more of a "coordination" tool for people working on features together keep questions and help to stackoverflow
EDIT: Removed as not to cause confusion
Please let me know if you have any suggestions or concerns.
This is and always will be a community effort, but I think this project will require that I either write v1 myself or with a group of core contributors. The community can provide feedback, request features, and additional people can make contributions from there.
Only volunteer if you're serious about the project and can contribute a large amount of code for v1 rather quickly. Each and every contributor is welcome but this is a special task ๐
Considering v0.4.0 is focusing on clean up and documentation this would be a good time to write a CONTRIBUTING.md and provide some basic guidelines for new contributors.
Hi,
When I try to input very long messages I get an extra margin at the top and the bottom of each bubbles.
After investigating I realised that if I change in MessagesCollectionViewFlowLayout.Swift (line 64) :
messageLabelFont = UIFont.preferredFont(forTextStyle: .body)
by
messageLabelFont = UIFont.systemFont(ofSize: 17) // This is the font used anyway in my UILabel
It works. Hope this helps.
Best regards,
Basically, we need to revert some of the changes made to MessagesDisplayDelegate
to return a configuration representing the AvatarView
instead of the AvatarView
itself. As discussed on Slack.
Avatar
model representing configuration for AvatarView
avatarImageView
in MessagesCollectionViewCell
with AvatarView
AvatarView.playground
to ChatExample
projectPlease submit changes to v0.3.0
branch ๐
It's going to conflict with native name someday, my first impression...
Originally, I wanted to eliminate the need for additional views inside of the MessageCollectionViewCell
's contentView
altogether.
However, this can limit the flexibility of the layout. For example:
You wouldn't be able to add a header whose top edge is in line with the Avatar
. Therefore, while using section Headers
and Footers
will be easier/more customizable in some cases -- I feel like this needs to be an option.
There should also be two flags that control how far these labels extend horizontally:
avatarShouldBeginBeforeTopLabel
avatarShouldBeginBeforeBottomLabel
Currently, MessageKit supports a cell structure shown in the figure below:
I originally added the cellTopLabel
and cellBottomLabel
to this cell because I wanted to be able to top align the avatar with other views and not just the messageLabel
.
While this allows the layout I was looking for, it also has some drawbacks. Namely, the cellTopLabel
and cellBottomLabel
are limited to UILabels
and multiple views increase the layout complexity for this cell.
We remove the cellTopLabel
, cellBottomLabel
, AND the AvatarView
from the cell. Instead, cellTopLabel
and cellBottomLabel
are replaced with their own cells. This should remove the UILabel
limitation.
We would just need a way to specify if the MessageCollectionViewCell
or MessageTopCell
contained the AvatarView
.
IGListKit does this really well. I could see it being a formal dependency in the future. Why? It makes sense not to reinvent the wheel.
But for now -- dependencies are off the table. If we make this change we will start with something small, in-house, and see where the architecture leads us.
Hi guys in this example i am demonstrated how to handle InputAccessoryView. Source code is in obj-c so feel free to convert
TextFieldDemo.zip
maybe it's better using tableview instead of collectionview
2 major issues - the overall layout is weird, and the sender name & date label alignment is ignored:
App Delegate looks like this to setup the tab bar controller:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
let iconSide: CGFloat = 34.0
let iconSize = CGSize(width: iconSide, height: iconSide)
let iconInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0)
let home = StoryVC()
home.view.backgroundColor = UIColor.orange
home.tabBarItem.image = UIImage(named: "home")?.resizedImage(iconSize)
home.tabBarItem.imageInsets = iconInsets
let write = UIViewController()
write.view.backgroundColor = UIColor.purple
write.tabBarItem.image = UIImage(named: "fish")?.resizedImage(iconSize)
write.tabBarItem.imageInsets = iconInsets
let read = UIViewController()
read.view.backgroundColor = UIColor.yellow
read.tabBarItem.image = UIImage(named: "glasses")?.resizedImage(iconSize)
read.tabBarItem.imageInsets = iconInsets
let profile = UIViewController()
profile.view.backgroundColor = UIColor.lightGray
profile.tabBarItem.image = UIImage(named: "avatar")?.resizedImage(iconSize)
profile.tabBarItem.imageInsets = iconInsets
let tabBarController = UITabBarController()
tabBarController.viewControllers = [home, story, read, profile]
// Make the Tab Bar Controller the root view controller
window?.rootViewController = tabBarController
window?.makeKeyAndVisible()
return true
}
And StoryVC looks like this exactly like the Chat example project:
import Foundation
import MessageKit
class StoryVC: MessagesViewController {
let dataSource = StoryDataSource()
override func viewDidLoad() {
super.viewDidLoad()
messagesCollectionView.messagesDataSource = self
messagesCollectionView.messageCellDelegate = self
messagesCollectionView.messagesLayoutDelegate = self
messageInputBar.delegate = self
dataSource.delegate = self
}
}
// MARK: - StoryDataSourceDelegate
extension StoryVC: StoryDataSourceDelegate {
func storyDataUpdated() {
messagesCollectionView.reloadData()
}
}
// MARK: - MessagesDataSource
extension StoryVC: MessagesDataSource {
func currentSender() -> Sender {
return dataSource.hyou
}
func numberOfMessages(in messagesCollectionView: MessagesCollectionView) -> Int {
return dataSource.msgs.count
}
func messageForItem(at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> MessageType {
return dataSource.msgs[indexPath.section]
}
}
// MARK: - MessagesDisplayDataSource
extension StoryVC: MessagesDisplayDataSource {
func avatar(for message: MessageType,
at indexPath: IndexPath,
in messagesCollectionView: MessagesCollectionView) -> Avatar
{
return dataSource.avatarFor(sender: message.sender)
}
func messageHeaderView(for message: MessageType,
at indexPath: IndexPath,
in messagesCollectionView: MessagesCollectionView)
-> MessageHeaderView?
{
return messagesCollectionView.dequeueMessageHeaderView(for: indexPath)
}
func messageFooterView(for message: MessageType,
at indexPath: IndexPath,
in messagesCollectionView: MessagesCollectionView)
-> MessageFooterView?
{
return messagesCollectionView.dequeueMessageFooterView(for: indexPath)
}
func cellTopLabelAttributedText(for message: MessageType,
at indexPath: IndexPath)
-> NSAttributedString?
{
let name = message.sender.displayName
return NSAttributedString(
string: name,
attributes: [
NSFontAttributeName: UIFont.preferredFont(forTextStyle: .caption1)
])
}
func cellBottomLabelAttributedText(for message: MessageType,
at indexPath: IndexPath)
-> NSAttributedString?
{
let formatter = DateFormatter()
formatter.dateStyle = .medium
let dateString = formatter.string(from: message.sentDate)
return NSAttributedString(
string: dateString,
attributes: [
NSFontAttributeName: UIFont.preferredFont(forTextStyle: .caption2)
])
}
}
// MARK: - MessagesLayoutDelegate
extension StoryVC: MessagesLayoutDelegate {
func headerViewSize(for message: MessageType,
at indexPath: IndexPath,
in messagesCollectionView: MessagesCollectionView) -> CGSize
{
return CGSize(width: messagesCollectionView.bounds.width, height: 4)
}
func footerViewSize(for message: MessageType,
at indexPath: IndexPath,
in messagesCollectionView: MessagesCollectionView) -> CGSize
{
return CGSize(width: messagesCollectionView.bounds.width, height: 4)
}
}
// MARK: - MessageCellDelegate
extension StoryVC: MessageCellDelegate {
func didTapAvatar(in cell: MessageCollectionViewCell) {
print("Avatar tapped")
}
func didTapMessage(in cell: MessageCollectionViewCell) {
print("Message tapped")
}
func didTapBottomLabel(in cell: MessageCollectionViewCell) {}
func didTapTopLabel(in cell: MessageCollectionViewCell) {}
}
// MARK: - MessageInputBarDelegate
extension StoryVC: MessageInputBarDelegate {
func sendButtonPressed(sender: UIButton, textView: UITextView) {
guard let text = textView.text else { return }
dataSource.add(text, sender: currentSender())
}
}
I did set break point and saw that the attributes.direction is set correctly and the cellTopLabel.textAlignment is set accordingly. Thoughts on what's causing the 2 issues?
As discussed by the MessageKit community we won't jump to a v1.0 release just yet.
Hey everyone ๐,
We're looking to make a solid v1.0
release of MessageKit in the next few days.
So this will be the last call to make suggestions for v1.0
You can look at the current state of the project on the v0.3.0
branch.
There are a few bugs regarding the layout of the cellTopLabel
/cellBottomLabel
and text alignment.
We're aware of these and will have them resolved later today, so please ignore them for now.
With v1.0
we should be able to support basic MessageCollectionViewCells
that look like this:
If we don't use UITextView
for the MessageLabel
we'll have to write the data detectors in-house.
UITextView currently supports:
It would be nice to also support:
As a user developing with MessageKit I want to be able to style my Data Detectors
text to make my app look fabulous even with custom backgrounds. Currently any text that is detected as a Phone Number, Address or email is a black underlined set of words.
We should be able to easily configure this with a convenience method.
As a MessageKit user I want the ability to customise the text style and color in a message. Often times incoming messages have a different background color and for readability I would like to be able to change the color of the text to provide better contrast.
Hey everyone ๐,
I've released MessageKit v0.3.0
. You can download it via CocoaPods or take a look at the zip.
This is still a pre-release but MessageKit is slowly becoming something of actual use.
AvatarView
class with an awesome initials placeholder feature. Thanks @MacMeDan!InputTextView
class with smarter placeholder and send button. Thanks @andreaantonioni!cellTopLabel
and cellBottomLabel
supporting NSAttributedString
MessageType
now supports case attributedText(NSAttributedString)
for messagesThe primary focus of v0.4.0 will be:
We have a small Slack community where we discuss the future of the project. You can join here.
There is no method to change the color of the text for an incoming Message
vs outgoing message
Hi,
when i return 0 in numberOfMessages delegate i get crash. So if i put to return 1 in this method then i get the crash in messageForItem because i access to empty array and it's tried to get first element message[1]. So i cannot handle case when i have no messages.
How can i fix this issue if i don't have any messages?
Hey everyone ๐
,
I've released MessageKit v0.5.0
. You can download it via CocoaPods or take a look at the zip.
NSAttributedString
for messagesdidSelectTopLabel
and didSelectBottomLabel
delegate methodsAvatarView
in cell relative to contentsAddress
, Phone Number
, URL
, and Date
to messages which also support tap handling@MacMeDan, @gungorbasa, @bojanstef for contributing on this release
Moving slowly has been very beneficial in making some key design decisions -- but this project cannot remain as a prerelease indefinitely.
Pre-release phases will end by the September 1st and my goals for this would be a version 0.9.0
.
You can see the full roadmap in the original issue.
Looking to get involved in the project? Come join us on at the MessageKit Slack Channel
Hey everyone ๐,
I've released MessageKit v0.2.0
. You can download it via CocoaPods or take a look at the zip.
UITextView
for MessageInputBar
didTapAvatar
and didTapMessage
You can also look at this boring CHANGELOG.md!
This project is in its earliest stages so the codebase is changing rather quickly. If you'd like to work on something please discuss it with me first so we can prevent merge conflicts.
You can get in contact with me directly on Slack. You can sign up here.
Hey everyone ๐,
I've released MessageKit v0.6.0. You can download it via CocoaPods or take a look at the zip.
MessageInputBar
has received a significant upgrade thanks to an awesome contribution by @nathantannar4@nathantannar4, @MacMeDan, @etoledom for contributing to this release
We missed our deadline for getting out of pre-release which is entirely my fault ๐ but we should only be a few days behind.
Looking to get involved in the project? Come join us on at the MessageKit Slack Channel
Hey everyone,
I've released MessageKit v0.1.0
. You can download it via CocoaPods or master
.
I think this goes without saying that this is a prerelease and not production ready. There is a lot of activity surrounding this project and I'm just trying to put something out there for everyone to work with.
"If you are not embarrassed by the first version of your product, youโve launched too late."
-Reid Hoffman
This project is in its earliest stages so the codebase is changing rather quickly. If you'd like to work on something please discuss it with me first so we can prevent merge conflicts.
Currently, we have no documentation for this project. The goal is to auto-generate some with Jazzy
and also provide more personalized documentation via markdown files.
However, writing documentation at this stage of the project, considering the unstable API, provides little to no value.
Therefore, if you're looking to get involved, please take a look at the Example Project.
I've also added a Code of Conduct. This CoC is taken seriously by the project owners.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.