• 开源镜像
  • 开源沙龙
  • 媛宝
  • 猿帅
  • 注册
  • 登录
  • 息壤开源生活方式平台
  • 加入我们

开源日报

  • 开源日报第559期:《快速展示 ScreenToGif》

    25 9 月, 2019
    开源日报 每天推荐一个 GitHub 优质开源项目和一篇精选英文科技或编程文章原文,坚持阅读《开源日报》,保持每日学习的好习惯。
    今日推荐开源项目:《快速展示 ScreenToGif》
    今日推荐英文原文:《The (One) Time I Had a Black Manager》

    今日推荐开源项目:《快速展示 ScreenToGif》传送门:GitHub链接
    推荐理由:有时你需要向朋友发送一个 gif:在游戏里的惊人操作,一个沙雕的代码效果……而截图很明显不能满足这个需求,发送视频又显得太麻烦。这个项目是一个录屏软件,尽管体积很小,但是一样五脏俱全——允许你录屏后转为视频或动图编辑之后保存,同时能够满足录制短过程和长过程的需求。
    今日推荐英文原文:《The (One) Time I Had a Black Manager》作者:Meka Seymour
    原文链接:https://blog.usejournal.com/the-one-time-i-had-a-black-manager-2eeb90395f2d
    推荐理由:某人人生中的一段小小故事

    The (One) Time I Had a Black Manager

    And how it shaped my career

    I got my first job when I was 16. A few weeks after I got my driver’s license, I drove my red, 2002 Ford Focus over to a local Frisch’s Big Boy. I’d never eaten there, but it always seemed to be empty which I thought was just the right level of intimidating for my first job.

    My would-be manager, a white man of around 60, conducted an informal interview with me at one of the empty tables — we had every seat in the place to choose from.

    With my resume in hand (which I can only imagine was just a blank piece of paper), he asked me questions about work ethic and why I wanted a job. I told him about how I’d gone to work with my parents at their shops almost every day after school and on the weekends. I told him I knew a thing or two about keeping a place in tip-top shape and having pride in my work. He liked that answer and hired me on the spot.

    He was my first manager and he gave me my first bullet on my blank sheet of paper.

    Fast forward six years, and five managers later, to 2016. ?

    One year into my first job out of college, an email popped into my inbox that caught my eye. Dion, a new engineering manager, had just been hired. There was a photo and a blurb where he’d been prompted to answer some questions about where he was from, what he was doing before this job, and what excited him about his new role. He said he was from Jamaica (like my mom), he was excited to get to know and work with everybody, and unlike any manager I’d ever met, he was black.

    I immediately looked him up on Slack and sent a message that said something like:

    “Welcome to [company]. You’re Jamaican, I’m Jamaican! I think we’re the only ones. Would you like to get coffee?”

    He responded saying he didn’t like coffee but would love to chat. I knew our friendship was off to a great start — I didn’t like coffee either!

    At the time, I was a CX agent, or as it’s called where I’m from, a customer service representative. I’d gone to college to study business — not because I didn’t know what else to study, as the stereotype of business majors goes, but because I really wanted to.

    When I graduated I didn’t know where I would fit in. Most of my classmates were going off to work in some of the most homogeneously dominated professions in the galaxy — investment banking and consulting. I knew I would be utterly alone there and couldn’t stomach the idea of feeling as out-of-place at work as I did in my college classes. So I packed my bags to go try my luck in the most diverse city in the country, at a startup I’d heard about from a friend, to fill the only role I could see myself in at the time — CX.

    What happened next changed the course of my career, and quite possibly, my life. Dion (my new blood brother) and I, sat on a bench outside of our office, drinking nothing, but the conversation was easy. We talked about our Jamaican mothers briefly, he told me about his experiences giving back — volunteering, mentoring, teaching — and I told him about mine. We’d both come a long way to be sitting on that bench. Knowing that was in our blood. Paying it forward was a necessary part of our journey. He asked me what I wanted to do in the future. I told him I’d been learning to code for fun because I was bored in my job, but I told him I definitely didn’t want to become an engineer — for the same reasons I had steered clear of investment banking and consulting.

    He half-heartedly tried to convince me otherwise but mostly listened, then told me we should grab not coffee again soon.

    Over the course of the next year, I brought him projects I was working on. He looked them over, told me to keep working, offered advice about where to focus my learning. On more than one occasion he told me I could “do it” even before I knew what “it” was. He was well-respected and smart, calculating but also compassionate and personable. He valued people — where they came from and where they were going. He was the first person I saw myself in since going to college. The first person in this strange world so far from where I’d started that helped me see that I could really do it, whatever it was.

    I kept working on my coding, building projects outside of work. Just when I was ready to leave the nest (set out for my life after [company]), he hired me onto his team as an apprentice software engineer, the first position of its kind at the company. He vouched for me. He assured the necessary people I‘d worked hard and could be successful in the role, pulled levers and opened doors. Behind closed doors, he told me I had a big challenge ahead of me and that everyone would be watching to see how this played out. He knew I understood — you can’t fail when you’re the first.

    I worked hard and before long I was contributing and pulling my weight on the team ahead of schedule — I was a bona fide engineer. Around the time I joined the engineering team , Dion had hired the only other Jamaican engineer I’d ever heard of, two Dominican engineers, a “bad-ass” female engineer from India, and two of the coolest white guys around. We were drawn to Dion like a light in the dark, and so, around him swelled a diverse team (like a perfectly-staged college brochure)— the best team I’ve ever been part of.

    Dion changed my life, and in no small part, because I could relate to him and he could relate to me. Dion was my manager for exactly one year. We still grab not coffees and talk about work and life. He gets it, and I’m forever grateful to have him to look up to and to have had, if for only a brief time, a black manager.

    The dream team ✌️
    下载开源日报APP:https://opensourcedaily.org/2579/
    加入我们:https://opensourcedaily.org/about/join/
    关注我们:https://opensourcedaily.org/about/love/
  • 开源日报第558期:《即刻 CopyTranslator》

    24 9 月, 2019
    开源日报 每天推荐一个 GitHub 优质开源项目和一篇精选英文科技或编程文章原文,坚持阅读《开源日报》,保持每日学习的好习惯。
    今日推荐开源项目:《即刻 CopyTranslator》
    今日推荐英文原文:《Stop Using Else in Your Programs》

    今日推荐开源项目:《即刻 CopyTranslator》传送门:GitHub链接
    推荐理由:读英文文档的时候基本上都会需要一个翻译器来辅助——即使读得多了也没准就有啥词给突然忘了呢。这个项目可以读取你的剪贴板,当你复制一段想要翻译的文字之后就会响应将其自动翻译,不需要额外的粘贴到其他翻译器上,也克服了划词翻译对大段文字的不适应,作为提升工作效率的道具来说相当合适,也能够在平时作为单纯的划词翻译来练习阅读能力。

    今日推荐英文原文:《Stop Using Else in Your Programs》作者:Joey Colon
    原文链接:https://medium.com/better-programming/why-you-need-to-stop-using-else-statements-5b1fd09dea9e
    推荐理由:在多个条件判定时一种比起堆叠 if-else 来说更整洁的写法

    Stop Using Else in Your Programs

    A practical introduction to guard clauses

    When I first began programming, I wish someone would have told me about a few different concepts to think about when writing my first website.

    One of the mistakes I fell into when starting was overusing the else keyword when writing conditionals. This is something that I find plenty of others doing in their own code as well, so I thought I should shed some light on the topic.

    A disclaimer; my view on this topic is purely subjective.

    In some situations, you may not be able to apply this type of approach to your code. Sometimes, the solution is to use the else keyword. This post is to inform people of an alternative approach to structuring logic.

    Indent Hadouken

    Guard Clauses

    According to Wikipedia, a guard clause is a check of integrity preconditions used to avoid errors during execution.

    Let’s break down that definition into layman’s terms. We perform a check of integrity preconditions (at the beginning of our code) to avoid any bugs during the main flow of our logic.

    In the perfect flow (when validation is correct), we want the main logic of our program to be after all of the validation checks.

    Let’s imagine that we run a website where we have a premium purchase area that is restricted to paying customers only and only open after 12 pm.
    <?php
    if ($user != null) {
        if (time() >= strtotime('12 pm')) {
            if ($user->hasAccess(UserType.PREMIUM)) {
                if ($store->hasItemsInStock()) {
                    // the content a premium user user should be able to see when the store is in stock 
                    // after 12pm.
                } else {
                    return 'We are completely sold out.';
                }
            } else {
                return 'You do not have premium access to our website.';
            }
        } else {
            return 'This section is not opened before 12PM';
        }
    } else {
        return 'You are not signed in.';
    }
    
    In an actual application, we would likely return some form of exception.

    While this is an approach to flow through the conditionals, the else keywords become difficult to follow even when we only have a small number of them.

    This is a trivial example of conditional logic but, out in the wild, imagine trying to navigate a class that has much more complex logic. Coding through this standard, in my opinion, is not sustainable and we should do better.

    With guard clauses, we will want to follow this framework:
    <?php
    if (condition1()) {
        return ...;
    }
    if (condition2()) {
        return ...;
    }
    // Input is valid.
    doSomething();
    
    Taking that framework, we can restructure the previous code like the following:
    <?php
    if ($user == null) {
        return 'You are not signed in.';
    }
    if (time() < strtotime('12 pm')) { 
        return 'This section is not opened before 12PM';
    }
    if (!$user->hasAccess(UserType.PREMIUM)) {
        return 'You do not have premium access to our website';
    }
    if (!$store->hasItemsInStock()) {
        return 'We are completely sold out.';
    }
    // the content a premium user user should be able to see when the store is in stock 
    // after 12pm.
    
    In guard clauses, we typically invert the boolean expression to what we want to assert. If we want the user to be signed in to view this page, we want to check if they’re not signed in.

    This approach captures the same exact logic flow but, in my opinion and in others as well, this is a much cleaner approach when tackling conditional logic.

    Conclusion

    When coding, we should always keep the question in-mind of: “How easy will this be to maintain 6 months down the line?”

    Creating solutions to a problem at the current time is great. But what about in the future? Not building software with the future in-mind is silly.

    It has personally caused me to entirely rewrite whole features from scratch because of how much technical debt I accumulated over time through numerous band-aid fixes.

    Utilizing guard clauses will set your future self/team up for success for when new requirements are added to your program.
    下载开源日报APP:https://opensourcedaily.org/2579/
    加入我们:https://opensourcedaily.org/about/join/
    关注我们:https://opensourcedaily.org/about/love/
  • 开源日报第557期:《彩虹猫 css-nyan-cat》

    23 9 月, 2019
    开源日报 每天推荐一个 GitHub 优质开源项目和一篇精选英文科技或编程文章原文,坚持阅读《开源日报》,保持每日学习的好习惯。
    今日推荐开源项目:《彩虹猫 css-nyan-cat》
    今日推荐英文原文:《The Mentality of a Software Engineer》

    今日推荐开源项目:《彩虹猫 css-nyan-cat》传送门:GitHub链接
    推荐理由:用纯 CSS 画出一只跑动的彩虹猫来。尽管不能做到 100% 的完全一致,但是已经有了彩虹猫的神态在里面。彩虹猫最初是出自一首歌词极其简单但是却十分洗脑的的歌曲《Nyan cat》,有人将猫与这首歌结合成动画之后才成为了现在广为流传的彩虹猫。如果你做好了被洗脑的准备的话可以试试看去听一听(传送门),如果听不懂也没关系,因为即使说的是猫语,你家的猫也是听不懂的。
    今日推荐英文原文:《The Mentality of a Software Engineer》作者:mvndy
    原文链接:https://medium.com/@hinchman_amanda/the-mentality-of-a-software-engineer-99fedf5248ee
    推荐理由:良好的心态与高等级的技术力一样重要

    The Mentality of a Software Engineer

    Someone probably told you that you don’t have the ability or the means to solve a problem. Someone probably told you “don’t worry about it”. Someone probably told you you can’t be the engineer you want to be.

    Like many women in engineering, I got my start in my career by working a job being assigned a lot of menial, repetitive tasks. When there was too much work to handle, I turned towards automation and native desktop development to do the jobs I didn’t want to do. At first, it got me in a lot of trouble. Later on, I was told the problems I want to solve is impossible — and nothing motivates me more than that.

    Truth of the matter is, when you’re equipped with the 5 essential principles of being a software engineer, only you can decide to be the engineer you want to be.

    1. Don’t present a problem; present a solution.

    You see a problem at work. It could be that production support is taking you away from sprint commitments. It could be that creating live demos three times a week is eating up the time you could be doing for your actual client work.

    A wise engineer once told me “don’t present a problem; present a solution”. It’s okay to identify the problem to your leaders — but if the problem is one you’ve been talking about for while, it might just make more sense to explore what it takes to create that solution. There is even more power to do so when working at a small-to-mid-size company!

    Examine the underlying factors and causes, and the role everyone plays in contributing to an issue. Enlist the right people to help solve the issue and get perspective about how certain processes work. Working cross-teams/cross-departments/writing automated solutions can be a lot of work, but it really shows initiative and creates bonds and synergy across the board for the people you work with. Working together to explore and solve pain points creates empathy for your teammates across the board!

    2. Don’t ask for permissions to solve problems.

    Your DNA test just came back: You don’t need permission to solve the problems you were paid to solve.

    If your team agrees that it’s okay to spend some time on prototyping, do so in a time-boxed setting. Otherwise, explore the solution on your free time and create an open-source version of the work to add to your Github!

    But how can a solution work for an organization if it requires collaboration across different teams or departments? I’ve found that grassroots movements are what works. By the time you propose an official idea in a meeting setting, it’s better to have key players in the room already agreeing with you and in on the idea. Bounce ideas off folks, get their input, and get information on how they approach a problem — teamwork is how grassroots movements become successful!

    I’ve definitely made mistakes in the past to propose whole new ideas to a room — without knowing what other’s workloads are, what they’re willing and able to contribute and the context of how other roles might play into a solution, it can feel like you’ve simply added workloads to others without figuring out what’s already being done, or that you’re simply stepping on others toes with duplicate effort.

    Take the time to explore possible difficulties and evaluate the amount of workload it might take if a solution requires a team effort. If there’s no team effort required and the solution is dependent on the work you put in, create a prototype of the solution you wish to propose. Being an engineer means you’re meant to solve problems — and it’s not always about code.

    3. Have a community — a safe space — where you can share your ideas and grow.

    I went from being shut-down daily to stumbling on an exciting and welcoming open-source community that is Kotlin. They didn’t just teach me a new language; they taught me it was okay to ask questions. I progressed from asking the “dumbest” questions to asking questions for things that don’t exist. They helped me push past the limits of the language, push past what I thought were my own limits — this community has been with me every step of the way and in every project I’ve taken on.

    Take what you learn and make open source versions of those lessons. If you’ve taken ideas and solutions from other open-source projects and articles, give the love back! Are you worried that what you’ve wrote has been written before? Well, that topic has yet to be explained by you! Writing is also important as a develop to help formulate how you express yourself as an engineer, and how you present new ideas to your colleagues, and just another way of giving back to your community.

    The local Kotlin community is another micro-community for me. I go to monthly meetups and it’s always great to see folks around the city. I’ve made so many friends here since I’ve moved up with no family here, and I can meet up with any of them for coffee any time to talk about code, jobs, or personal life!

    Additionally, local tech communities are how I look for new jobs! Tech groups are a great source for finding out who is working on what and what kind of technology is being used. Job descriptions never quite matches the engineering job, and this is hands down the best way to find capable folks and new teammates for specific projects.

    4. Failure is growth.

    Fail. Fail a lot. When you’re attempting to solve a new problem, take the time to do you research first. Struggle and flail on your own before asking for help. Getting help is fine and always recommended, but asking for help when you don’t know where to start won’t get you much help, and will fatigue those trying to help you.

    Struggling and flailing changes the conversation from this:

    “How do you [do this problem]?”

    To this:

    “I can’t figure this out! I have [done this to try and solve the problem], and I hit a wall when […]. I’ve tried […] and […], but these options don’t seem to work. I did notice some interesting behavior doing […], but I’m not sure it makes sense because [of certain assumptions made in research].”

    The second question not only gives you a chance to grow, but you’ll get far more specific answers. Asking these kinds of questions shows your mentors that you’ve prepared to use their time wisely and when you’ve put in the work to cover the basics, you leave time for mentors giving you specialized knowledge that is difficult to figure out on your own.

    5. Know your worth.

    Seriously. Know your worth. Know that failure is a sign of growth, and the sign of a good engineer. If you’re asking questions and it’s never the same question asked previously, you’re in a great place. Your title may not necessarily fit your actual job description, so it’s important to keep track of your successes — literally, a list of accomplishments with numbers to back them. See how you add value to your organization, and what responsibilities you’ve gained over time. Are you reducing time in processes by optimizing through automation? Have you rewritten a feature so that it works faster by x amount of seconds? WRITE IT DOWN.

    Do you research — check for descriptions/responsibilities of jobs. Talk about salaries with people you feel safe discussing it with.

    Having a job in tech is a lot like dating. You may be comfortable where you’re at, but if you’ve grown and do a lot more for your people, are you getting out what you put in? Or are you being convinced that you’re not worth as much as you’ve evaluated yourself? Like dating, if you’re in doubt about whether a company or a team values you, boil it down simply to actions (or inaction).

    Conclusion

    The essence of engineering is “if you haven’t been told you can’t do it, you probably can”. The caveat here is who tells you you can’t.

    Being a software engineer is really about having the confidence and grit to solve problems and fail in a safe space with a supportive community. People can tell you what you’re worth and tell you what you can and can’t do, but it’s really you who decides what kind of software engineer you want to be.
    下载开源日报APP:https://opensourcedaily.org/2579/
    加入我们:https://opensourcedaily.org/about/join/
    关注我们:https://opensourcedaily.org/about/love/
  • 开源日报第556期:《远程单位 awesome-remote-job》

    22 9 月, 2019
    开源日报 每天推荐一个 GitHub 优质开源项目和一篇精选英文科技或编程文章原文,坚持阅读《开源日报》,保持每日学习的好习惯。
    今日推荐开源项目:《远程单位 awesome-remote-job》
    今日推荐英文原文:《Object-Oriented Is Not Dead》

    今日推荐开源项目:《远程单位 awesome-remote-job》传送门:GitHub链接
    推荐理由:让从五湖四海来的所有员工集中在某地的一个办公室里似乎在现在重要性并没有这么强了。这个项目是关于远程工作的资源合集,包括文章与相关工具等。远程工作有利也有弊,没有地理位置的限制就可以招募到更广地区内的员工,省下的通勤时间也能换成工作时间,但是地理距离拉开之后保持高效的沟通就变得更加重要,没有了面对面的高效沟通,使用其他工具或者规则来补足这一点就显得极为重要。
    今日推荐英文原文:《Object-Oriented Is Not Dead》作者:Aphinya Dechalert
    原文链接:https://medium.com/better-programming/object-oriented-is-not-dead-eca233347870
    推荐理由:最起码,把所有东西都看作一个对象的观察法经受住了时间的考验

    Object-Oriented Is Not Dead

    Long Live OOP and its place in JavaScript

    Object-oriented programming (OOP) has gone through the mill of being adored, to suddenly hated by the masses. While it’s hard to discern how much of that love, hate, and intensity is fake news, the verdict is that the idea of object-oriented is not dead.

    The issue isn’t object-oriented itself. The issue is how object-oriented was, is, has been, implemented. Legacy methodologies of OOP such as inheritance patterns are being regarded as insufficient to deal with the modern demands of a much larger codebase with more moving parts.

    This isn’t OOP’s fault directly. Some patterns are simply behind in the times or are unsuitable at certain scales. Sometimes, the developer behind the code just hasn’t caught up with the memo yet, or they only know one OOP pattern.

    Everything Is an Object

    In the beginning, some guys at MIT in the late ‘50s came up with the idea that everything is an object. Sure, the idea of “objects” itself isn’t exactly new, but in programming, this was akin to a philosophical breakthrough.

    The way we function as a civilization depends on our ability to communicate our personal translations and experiences of the world. Language is the way we facilitate this — whether it be verbal, non-verbal, visual, performance arts, music, or writing that captures the complexities of an idea in a simple way. Sometimes we mix and match to further enrich our experience of the idea.

    For programmers, code is a communication bridge between us and digital machines. To classify everything as an object is a way to simplify the translation of business rules and interactions with their various action points.

    Objects are essentially an organization tool that may also contain descriptions and abilities to perform actions — also known as, properties and methods. How these properties and methods are internally arranged to construct the blueprint for the object, often known as a class, is dependent on the scenarios and the developer’s knowledge of different implementation of object-oriented patterns available.

    Most popular programming languages such as C++, Java, Python, and PHP all support the idea of objects. However, they also support other models of thinking and are not exclusively object-oriented, meaning that they are also capable of imperative and procedural methodologies.

    JavaScript is an ideological chameleon. It has some of its foundations in object-oriented through prototypes but also is able to cater to other paradigms because it was created to “just work” regardless of whatever code you typed in.

    JavaScript and Its Secret Love Affair With Objects

    In the eyes of the JavaScript engine, everything is an object.

    Your variables are objects. Your functions are objects. Your arrays, your numbers, even your Objects are objects. This is important because it means you can assign properties to them. It’s also why we have an assortment of predefined methods available to us such as .length() for arrays and .arguments() for functions.

    The confusion about JavaScript and its relationship with the object-oriented world starts where it begins.

    JavaScript isn’t a language that advertises itself as being object-oriented. In fact, you don’t even have to aware of such an idea for it to work. Unlike Java- and C-based languages, which require a level of syntax strictness, JavaScript’s general looseness adds to its generalized secret love affair with the idea of objects.

    Under the hood, JavaScript runs on a prototype pattern — which is a form of deconstructed chained inheritance object-oriented pattern that isn’t required to be singularly attached to one thing.

    Traditionally, object-oriented is taught in the vein that everything gets put into a class to make a blueprint for an object to instantiate. JavaScript takes a step back from all this and runs on the foundational idea that an object is something you can assign properties and methods to, regardless of its type and final expected shape.

    In JavaScript, everything begins as an object and ends as an object. Its definition of what an object looks like is based on two characteristics of having properties and methods, rather than the process of creating a traditional-looking object.

    Stop Right There. What About Functional Programming?

    Functional programming is a pattern that is currently being spoken about like it’s the thing that will put object-oriented into its grave. However, it’s a completely different method of translating ideas and runs on the premise of inputs, outputs, and functional machines.

    Object-oriented is concerned with the idea of things. In contrast, functional paradigms are concerned with the processing of things. In JavaScript, functional patterns often exist as predefined methods. For example, array methods such as filter(), find(), map() and reduce() are functional array methods that help reduce the complexity of code and potential points of failure.

    Over the years, programming languages have come to a silent consensus that a single way of thinking can’t possibly cover all the potential bases. It’s also why many programming languages have evolved to be multi-paradigm to prevent themselves from alienating developers with undetermined cases in the wild.

    JavaScript Is Extending Its Features and Functionality

    JavaScript started off as a simple scripting language. Over the years, it has gained supersets like TypeScript to give it a more traditional and strongly-typed approach to code creation.

    As JavaScript catches up by growing its syntax and ideological implementation toolkits, we are greeted with new keywords and concepts that make our lives easier as developers.

    The class keyword, for example, which was recently introduced in ES6, is merely syntax sugar to help make explicit the implementation of object-oriented ideas. The actual object-orientedness of JavaScript and its prototypal inheritance patterns remains more a meta-like and structural foundation for the language.

    Another new feature that’s currently in the final stage of review is private variables in classes. There is limited scope let but not an actual direct way of implementing the idea of private in JavaScript. When this goes through, you’ll be able to directly do so by declaring variables with a hashtag in front of the variable you want to scope as private to the declared class or function.

    Final Thoughts

    In the world of JavaScript, object-oriented isn’t really winding down. Rather, it is expanding syntactically to remain true to its spirit of flexibility.

    Everything is made of ideas and one of those ideas is that everything is an object. Whether this is true or not is a completely different and potentially existential debate.

    Object-oriented isn’t dead. Nor is it close to being dead. Rather, its hype has just deflated a little as the flaws in its implementation, such as classical inheritance patterns, come into view. However, patterns that don’t scale well don’t mean the end of ideas. Adaptations are growing as more people explore OOP to help solve their particular problems.

    Legacy code is always annoying to deal with and a lot of the time, it’s written with the idea of object-oriented in mind. However, one shouldn’t dismiss object-oriented completely, but learn from how things fell apart.

    At the end of the day, it doesn’t matter what paradigm or pattern you use. Your code will always age and chances are that someone in the near or far future will judge your chosen solution and deem it impractical because the code has grown out of its implemented patterns.

    So is object-oriented dead? Some say so, but in reality—far from it. In the world of web technologies and with JavaScript releasing more features and functionality to support making object-oriented patterns explicit, the idea of objects is still thriving loud and proud.

    Thank you for reading.
    下载开源日报APP:https://opensourcedaily.org/2579/
    加入我们:https://opensourcedaily.org/about/join/
    关注我们:https://opensourcedaily.org/about/love/
←上一页
1 … 119 120 121 122 123 … 262
下一页→

Proudly powered by WordPress